離線演算法:
先將所有涉及到的串建成字典樹,然後用線段樹維護dfs序,時間複雜度$O(m\log L)$。
線上演算法:
用替罪羊樹動態維護Trie樹的dfs序即可,時間複雜度$O(L\log L)$。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2100010,M=50010;const double A=0.77; int Type,n,m,i,x,y,loc[M],w[M],trie[N>>1][26],st[N>>1],en[N>>1],ct,ans; char op[5],s[N]; namespace Subtask1{ int cnt,dfn,v[N],tag[N],c,d,p; struct P{int x,y;P(){}P(int _x,int _y){x=_x,y=_y;}}q[250010]; void dfs(int x){ st[x]=++dfn; for(int i=0;i<26;i++)if(trie[x][i])dfs(trie[x][i]); en[x]=dfn; } inline void tag1(int x,int p){v[x]+=p;tag[x]+=p;} void change(int x,int a,int b){ if(c<=a&&b<=d){tag1(x,p);return;} if(tag[x])tag1(x<<1,tag[x]),tag1(x<<1|1,tag[x]),tag[x]=0; int mid=(a+b)>>1; if(c<=mid)change(x<<1,a,mid); if(d>mid)change(x<<1|1,mid+1,b); v[x]=max(v[x<<1],v[x<<1|1]); } inline void insert(int p){ gets(s); int l=strlen(s);register int x=0,i=0; for(int w;i<l;i++)if(s[i]>='a'){ if(!trie[x][w=s[i]-'a'])trie[x][w]=++ct; x=trie[x][w]; } loc[p]=x; } void work(){ for(i=1;i<=n;i++)insert(i); for(i=1;i<=n;i++)scanf("%d",&w[i]),q[++cnt]=P(loc[i],max(w[i],0)); while(m--){ scanf("%s",op); if(op[0]=='Q')q[++cnt]=P(-1,0); if(op[1]=='v'){ scanf("%d%d",&x,&y); q[++cnt]=P(loc[x],max(y,0)-max(w[x],0)); w[x]=y; } if(op[1]=='s'){ scanf("%d",&x); if(w[x]>0)q[++cnt]=P(loc[x],-w[x]); insert(x); if(w[x]>0)q[++cnt]=P(loc[x],w[x]); } } dfs(0); for(i=1;i<=cnt;i++)if(q[i].x<0)printf("%d\n",v[1]);else c=st[q[i].x],d=en[q[i].x],p=q[i].y,change(1,1,dfn); } } namespace Subtask2{ int size[N],son[N][2],val[N],h[N],tag[N],f[N],tot,root,data[N],id[N],cnt; int P,B,C,D; inline void umax(int&a,int b){if(a<b)a=b;} inline int newnode(int x,int p,int fa){ f[x]=fa;size[x]=1;son[x][0]=son[x][1]=0; h[x]=val[x]=p;tag[x]=0; return x; } inline void tag1(int x,int p){h[x]+=p;val[x]+=p;tag[x]+=p;} inline void pb(int x){ if(tag[x]){ if(son[x][0])tag1(son[x][0],tag[x]); if(son[x][1])tag1(son[x][1],tag[x]); tag[x]=0; } } inline void up(int x){ h[x]=val[x]; if(son[x][0])umax(h[x],h[son[x][0]]); if(son[x][1])umax(h[x],h[son[x][1]]); } int ins(int x){ size[x]++;pb(x); if(!son[x][B])return son[x][B]=newnode(++tot,P,x); return ins(son[x][B]); } void dfs(int x){ pb(x); if(son[x][0])dfs(son[x][0]); data[++cnt]=val[x];id[cnt]=x; if(son[x][1])dfs(son[x][1]); } int build(int fa,int l,int r){ int mid=(l+r)>>1,x=newnode(id[mid],data[mid],fa); if(l==r)return x; if(l<mid)size[x]+=size[son[x][0]=build(x,l,mid-1)]; if(r>mid)size[x]+=size[son[x][1]=build(x,mid+1,r)]; return up(x),x; } inline int rebuild(int x){cnt=0;dfs(x);return build(f[x],1,cnt);} inline int kth(int k){ register int x=root,rank,t; while(1){ size[x]++;pb(x); rank=size[son[x][0]]+1; if(k==rank)return x; if(k<rank)x=son[x][0];else k-=rank,x=son[x][1]; } } inline int rank(register int x){ int ans=size[son[x][0]]+1; while(f[x]){ if(son[f[x]][1]==x)ans+=size[son[f[x]][0]]+1; x=f[x]; } return ans; } inline void kthins(int k){ register int x=kth(k); if(son[x][0])B=1,x=ins(son[x][0]);else{ son[x][0]=newnode(++tot,P,x); x=son[x][0]; } while((double)size[son[x][0]]<A*size[x]&&(double)size[son[x][1]]<A*size[x])x=f[x]; if(!x)return; if(x==root){root=rebuild(x);return;} int y=f[x],b=son[y][1]==x,now=rebuild(x); son[y][b]=now; } inline void modify(int x,int a,int b){ if(!x)return; if(C<=a&&b<=D){tag1(x,P);return;} pb(x); int mid=a+size[son[x][0]]; if(C<=mid&&mid<=D)val[x]+=P; if(C<mid)modify(son[x][0],a,mid-1); if(D>mid)modify(son[x][1],mid+1,b); up(x); } inline int getval(int x){ cnt=0; for(register int i=x;i;i=f[i])id[++cnt]=i; while(cnt)pb(id[cnt--]); return val[x]; } inline void addleaf(int x,int y){ int k=rank(en[x]);P=getval(en[x]); st[y]=tot+2,en[y]=tot+1; kthins(k); kthins(k); } inline void subtreeadd(int x,int y){C=rank(st[x]),D=rank(en[x]),P=y;modify(root,1,tot);} inline void insert(int p){ gets(s); int l=strlen(s);register int x=0,i=0; for(int w;i<l;i++)if(s[i]>='a'){ w=(s[i]-'a'+ans)%26; if(!trie[x][w])addleaf(x,trie[x][w]=++ct); x=trie[x][w]; } loc[p]=x; } void work(){ root=build(0,st[0]=id[1]=1,tot=en[0]=id[2]=2); for(i=1;i<=n;i++)insert(i); for(i=1;i<=n;i++)scanf("%d",&w[i]),subtreeadd(loc[i],max(w[i],0)); while(m--){ scanf("%s",op); if(op[0]=='Q')printf("%d\n",ans=h[root]); if(op[1]=='v'){ scanf("%d%d",&x,&y); y=min(1000,y+ans%1000); subtreeadd(loc[x],max(y,0)-max(w[x],0)); w[x]=y; } if(op[1]=='s'){ scanf("%d",&x); if(w[x]>0)subtreeadd(loc[x],-w[x]); insert(x); if(w[x]>0)subtreeadd(loc[x],w[x]); } } } } int main(){ scanf("%d%d%d",&Type,&n,&m);gets(s); if(Type==1)Subtask1::work();else Subtask2::work(); return 0; }