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的代码

 

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