Description
有一个塔,他的名字叫做粽粑,粽粑的每一层都有一个颜色 .
粽粑非常厉害,它在吸收天地精华之后会长高.粽粑的长高方式有两种:
1.在塔顶长出一层.
2.在塔底长出一层,即原来的第一层变成第二层,第二层变成第三层,以此类推,新长出来的是第一层.
粽粑有可能在某个时刻不是很开心,这个时候它会撤销它的前若干次长高.
你现在想知道粽粑长高的奥秘,于是找到了粽粑,发现它的入口上写着这么一句话:要进入粽粑,请找出一段最长的塔的区间,满足翻转后颜色不变.
粽粑会不断的长高(或撤销),所以它每次长高(或撤销)后你都要回答.为了你的方便,粽粑一开始的高度为0。
Solution
这题就是一道SB字符串题,只要前面后面各维护一个回文树,每加入一个就更新一下,撤销就暴力撤销,时间复杂度是
O(nlog2σ)
,好像很优秀,让我们看看
n≤107
……还是放弃吧。
我们发现每次加入只会使答案不变,或+1或+2,那么只要维护前后的哈希值就够了。
Code
写的巨丑,常数极大,还T了一个点。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
#define ll long long
using namespace std;
const int N=10000010,mo=1000000007,ny=224299067;
char s[N*3];
struct node{
int l,r,ln;
int fr,rf;
int en,re;
}st[N];
short int a[N*3];
int z[N],top=0;
void add_fr(int &v,int ln,int t) {v=((ll)t*z[ln]+v)%mo;}
void add_en(int &v,int t) {v=((ll)v*z[1]+t)%mo;}
void del_fr(int &v,int ln,int t) {v=(((ll)v-(ll)t*z[ln-1])%mo+mo)%mo;}
void del_en(int &v,int t) {v=(((ll)v-t+mo)%mo*ny)%mo;}
int main()
{
freopen("tower.in","r",stdin);
freopen("tower.out","w",stdout);
int q;
scanf("%d",&q);
scanf("%s",s);
z[0]=1;
fo(i,1,q) z[i]=(ll)z[i-1]*107%mo;
st[0].l=q+1,st[0].r=q;
int lans=0;
ll ans=0;
fo(i,0,q-1){
int op=s[i*3]-'0',t=((s[i*3+1]-'0')*10+s[i*3+2]-'0'+lans)%100;
if(op==1){
++t;
st[top+1]=st[top],++top;
int fr=st[top].fr,rf=st[top].rf,ln=st[top].ln;
int l=st[top].l,r=st[top].r;
add_fr(fr,ln,t),add_en(rf,t);
st[top].l--,a[l-1]=t,a[l-2]=a[r+1]=0;
st[top].fr=fr,st[top].rf=rf;
del_en(st[top].fr,a[l+ln-1]),del_fr(st[top].rf,ln+1,a[l+ln-1]);
if(fr==rf) st[top].fr=fr,st[top].rf=rf,st[top].ln=ln+1;
add_en(fr,a[l+ln]),add_fr(rf,ln+1,a[l+ln]);
if(fr==rf) st[top].fr=fr,st[top].rf=rf,st[top].ln=ln+2;
fo(j,1,st[top].ln-ln) add_en(st[top].en,a[r-ln+1-j]),add_fr(st[top].re,ln+j-1,a[r-ln+1-j]);
}
else if(op==2){
++t;
st[top+1]=st[top],++top;
int en=st[top].en,re=st[top].re,ln=st[top].ln;
int l=st[top].l,r=st[top].r;
add_fr(en,ln,t),add_en(re,t);
st[top].r++,a[r+1]=t,a[l-1]=a[r+2]=0;
st[top].en=en,st[top].re=re;
del_en(st[top].en,a[r-ln+1]),del_fr(st[top].re,ln+1,a[r-ln+1]);
if(en==re) st[top].en=en,st[top].re=re,st[top].ln=ln+1;
add_en(en,a[r-ln]),add_fr(re,ln+1,a[r-ln]);
if(en==re) st[top].en=en,st[top].re=re,st[top].ln=ln+2;
fo(j,1,st[top].ln-ln) add_en(st[top].fr,a[l+ln-1+j]),add_fr(st[top].rf,ln+j-1,a[l+ln-1+j]);
}
else top-=t;
lans=st[top].ln,ans+=lans;
}
printf("%lld",ans);
}