COCI 2012/2013 Contest #6

Problems-PDF

快读异或没注意优先级我是傻逼。


BAKA

小模拟一下就完事了。

#include<bits/stdc++.h>
using namespace std;
map<char,int> p;
int ans=0;
int main()
{
	p['A']=2,p['B']=2,p['C']=2;
	p['D']=3,p['E']=3,p['F']=3;
	p['G']=4,p['H']=4,p['I']=4;
	p['J']=5,p['K']=5,p['L']=5;
	p['M']=6,p['N']=6,p['O']=6;
	p['P']=7,p['Q']=7,p['R']=7,p['S']=7;
	p['T']=8,p['U']=8,p['V']=8;
	p['W']=9,p['X']=9,p['Y']=9,p['Z']=9;
	string a;
	cin>>a;
	for(int i=0;i<a.size();i++)
		ans+=(p[a[i]]+1);
	printf("%d\n",ans);
	return 0;
}

SUME

最暴力也是思考起来最简单的办法。

把所有方程(左下或右上的三角形),得到的和是\((n-1)(a_1+a_2...+a_n)\),可以计算出\((a_1+a_2...+a_n)\)的值。

然后对于\(a_i\),把和它有关的方程加起来,得到\(a_i+a_1+a_i+a_2...+a_i+a_{i-1}+a_i+a_{i+1}...+a_i+a_n\),即\((n-1)a_1+a_2+a_3...+a_n\),减去一个\((a_1+a_2...a_n)\),就可以计算出\((n-2)a_i\),除以\((n-2)\)即为答案。

不要问为什么是\(O(n^2)\)的,输入都是\(O(n^2)\)的,时间复杂度啥的就无所谓了(bushi)。

最后,注意开longlong(血泪的教训)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[1010][1010];
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0')
	{
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
signed main()
{
	int n,c=0;
	scanf("%lld",&n);
	if(n==2)
	{
		puts("1 1");
		return 0;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			a[i][j]=read();
	for(int i=2;i<=n;i++)
		for(int j=1;j<i;j++)
			c+=a[i][j];
	c/=(n-1);
	for(int k=1;k<=n;k++)
	{
		int cnt=0,ans=n-1;
		for(int j=1;j<=n;j++)
			cnt+=a[k][j];
		printf("%lld ",(cnt-c)/(n-2));
	}
	puts("");
	return 0;
} 

DBORI

首先想到\(O(n^2)\)处理处任意两个元素的和值。

然后可以考虑用一个数组\(n[k]\)表示\(k\)是否能够由两个元素相加得到。由于有个位置之前的限制,所以记录\(n[k]=i\)的意义是,\(k\)能够由\(a[i]\)和一个 \(a[j](1\leq j\leq i)\)相加得到。

由于有正负,所以分段存储就行了。

处理和判断可以同时进行。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[20010];
int f[20010];
int nz[600010];
int nf[600010];
signed main()
{
	int n;
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		for(int j=1;j<=i;j++)
		{
			int k=a[i]+a[j];
			if(k>=0&&!nz[k])nz[k]=i;
			else if(k<0&&!nf[-k])nf[-k]=i;
			int p=(a[i]-a[j]>=0)?nz[a[i]-a[j]]:nf[a[j]-a[i]];
			if(p&&p<i&&j!=i)f[i]=1;
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		ans+=f[i];
	printf("%lld\n",ans);
	return 0;
}

BUREK

容易发现能切割一个三角形的线就是在三角形横坐标覆盖范围内的或者是纵坐标覆盖范围内的。

那么容易得到一个三角形横纵坐标的极差,给范围内除端点外的点加一,查询的时候直接输出就可以了。

发现会超时,于是上个基础数据结构搞一搞就好了。

#include<bits/stdc++.h>
using namespace std;
inline int lowbit(int x)
{
	return x&-x;
}
int c[2][5000010];
const int MX=2e6+10;
const int ADD=1;
inline void adde(int x,int v,int k)
{
	for(int i=x;i<=MX;i+=lowbit(i))
		c[k][i]+=v;
}
inline void add(int x,int y,int v,int k)
{
	adde(x,v,k);
	adde(y+1,-v,k);
}
inline int ask(int x,int k)
{
	int cnt=0;
	for(int i=x;i;i-=lowbit(i))
		cnt+=c[k][i];
	return cnt;
}
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0')
	{
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0')
	{
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
int a[6];
int main()
{
	int n,m;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		for(int k=0;k<6;k++)
		{
			a[k]=read();
			a[k]+=ADD;
		}
		//1x0y
		int q=min(min(a[0],a[2]),a[4]),w=max(max(a[0],a[2]),a[4]);
		int e=min(min(a[1],a[3]),a[5]),r=max(max(a[1],a[3]),a[5]);
		add(q+1,w-1,1,1);
		add(e+1,r-1,1,0);
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		string xy,d;
		cin>>xy>>d;
		int c;
		c=read();
		printf("%d\n",ask(c+ADD,xy=="x"?1:0));
	}
	return 0;
}

剩下两道题下次丕定补。

posted @ 2020-10-07 16:46  摸鱼酱  阅读(155)  评论(0编辑  收藏  举报