這道題改題時我打了個玄學複雜度的暴力,然後我成功的造了一組數據hack掉了自己的代碼。。。。
通過觀察,我們可以很容易的發現在操作幾次後,整個序列就會變成一塊一塊相同的字母。
於是我們可以對我們的暴力做一些優化:在將字母塞進桶中時,不是一個一個往裏塞,而是將一段連續的區間O(1)塞進桶中。
實現也很簡單:在每次操作後,存下每個塊的左右端點,塞進去的時候注意把包含l,r的塊斷開,即可愉快的AC並且代碼跑的快的飛起。
但是有一個問題:處理l,r所在塊的邊界時,需要暴力找到這兩個塊的邊界,如果塊特別大,那麼每次尋找都是O(n)的,然後就愉快的T了(反正我自己造的100000個a跑了6s)
附超快AC代碼:
1 #include<cstdio> 2 char s[100001],bx[100001];int br[100001],b[127],n,m; 3 main(){ 4 scanf("%d%d%s",&n,&m,s+1);br[n+1]=n+1; 5 for(int i=1;i<=n;++i)br[i]=i,bx[i]=s[i]; 6 for(int i=1,l,r,x;i<=m;++i){ 7 scanf("%d%d%d",&l,&r,&x); 8 int j;for(j=l;!br[j];--j); 9 int k=br[j]+1;if(j!=l)b[bx[j]]+=br[j]-l+1,br[j]=l-1;else k=j; 10 while(br[k]<=r){ 11 b[bx[k]]+=br[k]-k+1; 12 int lst=k;k=br[k]+1;br[lst]=0; 13 } 14 if(k<=r)b[bx[k]]+=r-k+1,br[r+1]=br[k],bx[r+1]=bx[k],br[k]=0; 15 if(x)for(char ch='a';ch<='z';++ch)if(b[ch])br[l]=l+b[ch]-1,bx[l]=ch,l=br[l]+1,b[ch]=0; 16 if(!x)for(char ch='z';ch>='a';--ch)if(b[ch])br[l]=l+b[ch]-1,bx[l]=ch,l=br[l]+1,b[ch]=0; 17 } 18 for(int i=1;i<=n;i=br[i]+1)for(int j=i;j<=br[i];++j)putchar(bx[i]); 19 }