Codeforces Round #427 (Div. 2) [ C. Star sky ] [ D. Palindromic characteristics ] [ E. The penguin's game ]

本来准备好好打一场的,然而无奈腹痛只能带星号参加 (我才不是怕被打爆呢!)

PROBLEM C - Star sky

   OvO http://codeforces.com/contest/835/problem/C

  835C

  由于题目中给的c很小,可以对应每种亮度分别保存(c+1)个矩阵

  然后初始化一下求前缀矩阵

  每次询问就可以O(c)求出答案

(Accepted)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int M=144;
const int MM=100;

int mp[M][M][20];
int pre[M][M][20];
int n,q,c;
int ans;

void init()
{
	int i,j,k;
	memset(pre,0,sizeof(pre));
	for(i=1;i<=MM;i++)
		for(j=1;j<=MM;j++)
			for(k=0;k<=c;k++)
				pre[i][j][k]=pre[i-1][j][k]+pre[i][j-1][k]-pre[i-1][j-1][k]+mp[i][j][k];
}

int main()
{
	int chg,tmp,i,j,x,y,z,x1,y1,x2,y2,t;
	cin>>n>>q>>c;
	memset(mp,0,sizeof(mp));
	for(i=1;i<=n;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		mp[x][y][z]++;
	}
	init();
	while(q--)
	{
		scanf("%d%d%d%d%d",&t,&x1,&y1,&x2,&y2);
		ans=0;
		for(i=0;i<=c;i++)
		{
			chg=(i+t)%(c+1);
			tmp=pre[x2][y2][i]-pre[x1-1][y2][i]-pre[x2][y1-1][i]+pre[x1-1][y1-1][i];
			ans+=tmp*chg;
		}
		cout<<ans<<endl;
	}
	return 0;
}

  

PROBLEM D - Palindromic characteristics

  OWO http://codeforces.com/contest/835/problem/D

  835D

  对每两点做字符串哈希,然后搜索加记忆化(每搜索一段到一段合法的继续搜左右两边,递归,得到该段的类型,并且用类型来标记该段已经搜过)

  这样搜索的时间是O(n*n),然后O(1)判断哈希值是否相等,是的话就把对应计数值+1

  pretest能过,最后会不会挂掉就看我取的模了(趁终测还没结束赶紧睡觉~☆)(没挂嘿嘿嘿)

  

(Accepted)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

typedef unsigned long long ull;

const int M=5022;
const int bas=14123;

int ans[M];
char s[M];
int num[M];
int n;
unsigned hsh[M][M];
int flag[M][M];

void init()
{
	int i,j;
	n=strlen(s+1);
	for(i=1;i<=n;i++)
	{
		if(s[i]>='a')
			num[i]=s[i]-'a';
		else
			num[i]=s[i]-'A'+26;
	}
	memset(ans,0,sizeof(ans));
	memset(flag,-1,sizeof(flag));
	for(i=1;i<=n;i++)
	{
		hsh[i][i]=num[i];
		for(j=i+1;j<=n;j++)
			hsh[i][j]=hsh[i][j-1]*bas+num[j];
		for(j=i-1;j>=1;j--)
			hsh[i][j]=hsh[i][j+1]*bas+num[j];
	}
}

bool fj(int a,int b,int c,int d)
{
	return true;
	int i,j;
	for(i=a,j=d;i<=b;i++,j--)
		if(num[i]!=num[j])
			return false;
	return true;	
}

int check(int a,int d)
{
	if(a==d) 
	{
		flag[a][d]=1;
		return 1;
	}
	int tmp=(d-a+1)/2;
	int b,c;
	b=a+tmp-1; c=d-tmp+1;
//	cout<<a<<' '<<b<<' '<<c<<' '<<d<<' '<<hsh[a][b]<<' '<<hsh[d][c]<<endl;
	if(hsh[a][b]==hsh[d][c] && fj(a,b,c,d))
	{
	
		int flag0,flag1,flag2;

		if(flag[a][b]!=-1) 
			flag1=flag[a][b];
		else
		{
			flag1=check(a,b);
			flag[a][b]=flag1;
			ans[flag1]++;
		}
			
		if(flag[c][d]!=-1)
			flag2=flag[c][d];
		else
		{
			flag2=check(c,d);
			flag[c][d]=flag2;
			ans[flag2]++;
		}
		flag0=min(flag1,flag2);
			return flag0+1;
	}
	else 
	{
		flag[a][d]=0;
		return 0;
	}
}

void solve()
{
	int i,j,a,b,c,d,len,tmp;
	for(i=1;i<=n;i++)
	{
		for(j=i;2*j-i<=n;j++)
		{
			if(2*j-i<=n)
			{
				a=i; d=2*j-i; len=d-a+1;
				if(flag[a][d]==-1)
				{
					tmp=check(a,d);
					flag[a][d]=tmp;
					ans[tmp]++;
				}
			}
			if(2*j-i+1<=n)
			{
				a=i; d=2*j-i+1; len=d-a+1;
				if(flag[a][d]==-1)
				{					
					tmp=check(a,d);
					flag[a][d]=tmp;
					ans[tmp]++;
				}
			}
		}
	}
	for(i=n;i>=1;i--)
		ans[i]+=ans[i+1];
	for(i=1;i<=n;i++)
	{
		if(i-1) printf(" ");
		printf("%d",ans[i]);
	}
	printf("
");
}

int main()
{
	int i,j;
	scanf("%s",s+1);
	init();
	solve();
	return 0;
}

  

一结束我就写了题解 怎么会有我这么勤奋的人呢 我真是太了不起了~☆

PROBLEM E - The penguin's game

  OwO http://codeforces.com/contest/835/problem/E

  835E

  设要不同的2个点为p,q

  1. n的范围为1000,所以最多有10位。所以可以枚举每一位,对该为为1的数字输出,这样可以知道p,q哪些位数不同。(至多10次输出)

  2. p,q不同的位的数量至少为1。所以可以随便选取一位,然后,选出该位为1的数字,放入集合中,则这个集合中最多只有1个特殊点(设其为p),所以可以二分区间寻找改p(至多9次输出)

  3. 找到p点之后,根据第1步中得到的p和q中各位的关系,得到q

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;

const int N=33;
const int M=1111;

int n,x,y;
int dif[N],chs;
int se[N][M],lse[N];
int rep;

void ask(int len,int s[])
{
	printf("? %d",len);
	for(int i=1;i<=len;i++)
		printf(" %d",s[i]);
	printf("
");
	fflush(stdout);
	scanf("%d",&rep);
}

void output(int ans1,int ans2)
{
	printf("! %d %d
",ans1,ans2);
	fflush(stdout);
}

void init()
{
	int i,j,mdl;
	memset(lse,0,sizeof(lse));
	for(i=1;i<=n;i++)
	{
		for(j=0;j<10;j++)
		{
			mdl=(1<<j);
			if(i&mdl)
				se[j][++lse[j]]=i;
		}
	}
	chs=-1;
	memset(dif,0,sizeof(dif));
	for(i=0;i<10;i++)
		if(lse[i]!=0)
		{
			ask(lse[i],se[i]);
			if(rep!=0 && rep!=x)
			{
				dif[i]=1;
				if(chs==-1)
					chs=i;
			}
		}
}

void solve()
{
	int ans1,ans2;
	int s[M],ls;
	int i,j,tmp;
	ls=0;
	for(i=1;i<=n;i++)
		if(i&(1<<chs))
			s[++ls]=i;
	int li,ri,mid;
//	for(i=1;i<=ls;i++)
//		cout<<s[i]<<' ';
//	cout<<endl;
	li=1; ri=ls;
	while(li!=ri)
	{
		mid=(li+ri)>>1;
		ask((mid-li+1),s+li-1);
		if(rep==0 || rep==x)
			li=mid+1;
		else
			ri=mid;
	}
	ans1=s[li];
	ans2=ans1^(1<<chs);
	for(i=0;i<10;i++)
		if(i!=chs && dif[i]==1)
			ans2^=(1<<i);
	if(ans1>ans2) swap(ans1,ans2);
	output(ans1,ans2);
}

int main()
{
	cin>>n>>x>>y;
	init();
	solve();
	return 0;
}

  

原文地址:https://www.cnblogs.com/FxxL/p/7266431.html