CF1392G Omkar and Pies 題解
阿新 • • 發佈:2022-05-28
考慮如果把同樣的一段操作序列同時給兩個串做,對答案是沒有影響的。所以考慮把每個區間差分成字尾(不能是字首,因為這樣相同的操作序列在前面沒法抵消),這樣就可以表示區間了。兩個串分別的對每個字尾操作之後得到的串可以 \(O(nk)\) 算出來,就是記錄每個位置最終會被換到哪裡就可以從右向左遞推。
算出兩個串前後綴之後(設為 \(a_i,b_i\)),考慮如何計算答案:設 \(a,b\) 中 \(1\) 的個數分別為 \(p,q\),\(a,b\) 重合的 \(1\) 的個數為 \(r\),那麼答案為 \(k-p-q+2r\)。\(k,p,q\) 都是常數,現在只需要使 \(r\) 最大。注意到最終的情況只有 \(2^k\)
所以總的複雜度為 \(O(nk+k2^k)\),可以通過此題。
點選檢視程式碼
const int N=1e6+13,M=(1<<20)+13,K=20+1; int n,m,k,l[N],r[N],a[N],b[N],f[M],g[M]; int pos[N][K]; char ina[K],inb[K]; int main(){ //file(); read(n),read(m),read(k); read(ina),read(inb); for(int i=1;i<=n;++i){ read(l[i]),read(r[i]); --l[i],--r[i]; } int x=0,y=0,p=0,q=0; for(int i=0;i<k;++i) p+=(ina[i]=='1'),q+=(inb[i]=='1'); for(int i=0;i<k;++i) pos[n+1][i]=i; for(int i=n;i;--i){ for(int j=0;j<k;++j){ if(j==l[i]) pos[i][j]=pos[i+1][r[i]]; else if(j==r[i]) pos[i][j]=pos[i+1][l[i]]; else pos[i][j]=pos[i+1][j]; } } for(int i=1;i<=n+1;++i){ static int ta[K],tb[K]; for(int j=0;j<k;++j) ta[pos[i][j]]=(ina[j]=='1'),tb[pos[i][j]]=(inb[j]=='1'); for(int j=0;j<k;++j) a[i]=(a[i]<<1)+ta[j],b[i]=(b[i]<<1)+tb[j]; } for(int i=0;i<(1<<k);++i) f[i]=n+1; for(int i=n+1;i;--i) f[a[i]]=i; for(int i=1;i<=n+1;++i) g[b[i]]=i; int ans=0,ansl=1,ansr=1; for(int s=(1<<k)-1;s>=0;--s){ int cnt=0; for(int i=0;i<k;++i) cnt+=((s>>i)&1); if(cnt>ans&&g[s]-f[s]>=m) ans=cnt,ansl=f[s],ansr=g[s]-1; for(int i=0;i<k;++i){ if(!((s>>i)&1)) continue; f[s^(1<<i)]=min(f[s^(1<<i)],f[s]); g[s^(1<<i)]=max(g[s^(1<<i)],g[s]); } } println(k-p-q+2*ans);print(ansl),print(' '),println(ansr); return 0; }