Codeforces Round #578 (Div. 2)
A.模拟。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 typedef long long ll; 7 using namespace std; 8 9 const int N=200010; 10 char s[N]; 11 int n,b[N]; 12 13 int main(){ 14 scanf("%d%s",&n,s+1); 15 rep(i,1,n){ 16 if (s[i]=='L') rep(j,0,9) if (!b[j]){ b[j]=1; break; } 17 if (s[i]=='R') for (int j=9; ~j; j--) if (!b[j]){ b[j]=1; break; } 18 if (s[i]>='0' && s[i]<='9') b[s[i]-'0']=0; 19 } 20 rep(i,0,9) if (b[i]) putchar('1'); else putchar('0'); 21 return 0; 22 }
B.为了积累积木,一定是走到h[i]-k的高度。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 typedef long long ll; 7 using namespace std; 8 9 const int N=2000010; 10 int T,n,m,k,h[N]; 11 12 int main(){ 13 for (scanf("%d",&T); T--; ){ 14 scanf("%d%d%d",&n,&m,&k); bool flag=0; 15 rep(i,1,n) scanf("%d",&h[i]); 16 rep(i,1,n-1){ 17 if (h[i]<h[i+1]-k){ 18 if (m<h[i+1]-k-h[i]){ flag=1; break; } 19 m-=h[i+1]-k-h[i]; continue; 20 } 21 m+=h[i]-max(h[i+1]-k,0); 22 } 23 if (flag) puts("NO"); else puts("YES"); 24 } 25 return 0; 26 }
C.都知道怎么做,关键就是把它变成代码。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 typedef long long ll; 7 using namespace std; 8 9 ll n,m,s1,s2,sx,sy,ex,ey; 10 int Q; 11 12 ll gcd(ll a,ll b){ return b ? gcd(b,a%b) : a; } 13 14 int main(){ 15 cin>>n>>m>>Q; 16 rep(i,1,Q){ 17 cin>>sx>>sy>>ex>>ey; s1=n/gcd(n,m); s2=m/gcd(n,m); 18 if (sx==1 && ex==1) puts((sy-1)/s1==(ey-1)/s1?"YES":"NO"); 19 else if (sx==2 && ex==2) puts((sy-1)/s2==(ey-1)/s2?"YES":"NO"); 20 else if (sx==1 && ex==2) puts((sy-1)/s1==(ey-1)/s2?"YES":"NO"); 21 else if (sx==2 && ex==1) puts((sy-1)/s2==(ey-1)/s1?"YES":"NO"); 22 } 23 return 0; 24 }
D.若想将一行全部变成白色,则选取矩形的左上角是在一个矩形里的,一列也一样。于是这就是个矩形加问题,二维差分即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 typedef long long ll; 7 using namespace std; 8 9 const int N=2010; 10 int n,k; 11 char s[N][N]; 12 int a[N][N],b[N][N]; 13 14 int main(){ 15 scanf("%d%d",&n,&k); 16 rep(i,1,n) scanf("%s",&s[i][1]); 17 int ans=0; 18 rep(i,1,n){ 19 int mn=n+1,mx=0; 20 rep(j,1,n) if (s[i][j]=='B') mn=min(mn,j),mx=max(mx,j); 21 if (mn==n+1) ++ans; 22 else if (mx-mn+1>k) continue; 23 else{ 24 int x=max(1,i-k+1),y=max(1,mx-k+1); 25 rep(j,x,i) a[j][y]++,b[j][mn+1]++; 26 } 27 } 28 rep(i,1,n){ 29 int mn=n+1,mx=0; 30 rep(j,1,n) if (s[j][i]=='B') mn=min(mn,j),mx=max(mx,j); 31 if (mn==n+1) ++ans; 32 else if (mx-mn+1>k) continue; 33 else{ 34 int x=max(1,mx-k+1),y=max(1,i-k+1); 35 rep(j,x,mn) a[j][y]++,b[j][i+1]++; 36 } 37 } 38 int Ans=0; 39 rep(i,1,n){ 40 int tot=0; 41 rep(j,1,n){ 42 tot+=a[i][j]; tot-=b[i][j]; 43 Ans=max(Ans,tot+ans); 44 } 45 } 46 cout<<Ans; 47 return 0; 48 }
E.一个做法是依次做,比较前后缀是否相同时用Hash。另一个做法是每次对新加入的串求KMP中的fail数组,然后扫一遍求出前面合成出的串与新加入的串的最长匹配长度。
1 #include<string> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 using namespace std; 7 8 const int p1=131,p2=998244353; 9 int n; 10 string s,res; 11 12 int main(){ 13 for (scanf("%d",&n); n--; ){ 14 cin>>s; 15 int l=0,r=0,p=1,c=0,ed=min(res.size(),s.size())-1,len=res.size(); 16 rep(i,0,ed){ 17 l=(l+1ll*res[len-i-1]*p)%p2,r=(1ll*r*p1+s[i])%p2,p=1ll*p*p1%p2; 18 if (l==r) c=i+1; 19 } 20 res+=s.substr(c); 21 } 22 cout<<res<<endl; 23 return 0; 24 }
1 #include<string> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 using namespace std; 7 8 const int N=1000010; 9 string res,s; 10 int n,fail[N]; 11 12 int main(){ 13 ios::sync_with_stdio(0); cin.tie(0); 14 cin>>n>>res; 15 while (--n){ 16 cin>>s; fail[0]=0; 17 for (int i=1,j=0; i<(int)s.length(); i++){ 18 fail[i]=0; 19 while (j>0 && s[i]!=s[j]) j=fail[j-1]; 20 if (s[i]==s[j]) fail[i]=++j; 21 } 22 int j=0; 23 for (int i=max(0,(int)res.length()-(int)s.length()); i<(int)res.length(); i++){ 24 while (j>0 && res[i]!=s[j]) j=fail[j-1]; 25 if (res[i]==s[j]) j++; 26 } 27 for (; j<(int)s.length(); j++) res+=s[j]; 28 } 29 cout<<res<<endl; 30 return 0; 31 }
F.每个点拆成2520份然后直接跑记忆化搜索即可。
1 #include<vector> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 using namespace std; 7 8 const int N=1010,mod=2520; 9 int n,Q,x,y,dep,f[N][mod],tim[N],k[N]; 10 vector<int>to[N]; 11 12 int dfs(int x,int y){ 13 if (f[x][y]>0) return f[x][y]; 14 if (f[x][y]<0){ 15 int sz=0; 16 rep(i,1,n) sz+=tim[i]<=f[x][y]; 17 return f[x][y]=sz; 18 } 19 f[x][y]=tim[x]=--dep; 20 return f[x][y]=dfs(to[x][(y+k[x])%to[x].size()],(y+k[x])%mod); 21 } 22 23 int main(){ 24 ios::sync_with_stdio(0); cin.tie(0); 25 cin>>n; 26 rep(i,1,n) cin>>k[i],k[i]=(k[i]%mod+mod)%mod; 27 rep(i,1,n) for (cin>>x; x--; ) cin>>y,to[i].push_back(y); 28 for (cin>>Q; Q--; ) cin>>x>>y,y=(y%mod+mod)%mod,cout<<dfs(x,y)<<endl; 29 return 0; 30 }