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("\n"); } 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("\n"); fflush(stdout); scanf("%d",&rep); } void output(int ans1,int ans2) { printf("! %d %d\n",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; }