noip11 string

這道題改題時我打了個玄學複雜度的暴力,然後我成功的造了一組數據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 }
這是dEEPINc的代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章