BZOJ2690: 字符串游戏(平衡树动态维护Dfs序)

Description

给定N个仅有a~z组成的字符串ai,每个字符串都有一个权值vi,有M次操作,操作分三种:
Cv x v':把第x个字符串的权值修改为v'
Cs x a':把第x个字符串修改成a'
Q:求出当前的最大权字符串集合,使得这个集合中的字符串经过重新排列后满足除最后一个字符串外,前一个字符
串是后一个的前缀(两个字符串相同也是前缀关系,也可以一个字符串都不选)
前50%的数据可以接受离线算法,后50%的数据要求在线算法。

Input

输入的第一行包含一个正整数Test表示当前的数据类型。
输入的第二行包含两个正整数N,M表示字符串数和操作数。
以下N行,每行一个字符串ai
第N+3行包含N个整数vi
以下M行,为M次操作,操作有三种Cv x v',Cs x a',Q,第三种操作如题目描述一样,对于Test=1的修改操作,不用
做 任何变化,对于Test=2的修改操作,假设当前最后一次询问操作的答案是ans(如果还没有询问操作,ans=0),那
么对于第 一种操作中的v'=min(1000,v'+(ans mod 1000)),对于第二种操作的字符串a',它的每一位都要加上ans m
od 26(a~z循环)
数据分两种,A类数据可以用离线的方法来完成,B类数据必须使用在线算法。
令len=输入数据中所有出现的字符串总长度
数据分两种,A类数据可以用离线的方法来完成,B类数据必须使用在线算法。
N<=50000,M<=10^5,Len<=10^6
 
 

Output

对于每一次询问输出合法的最大权字符串集合的权值和

Sample Input

1
5 5
aba
ab
babb
abaa
abab
-2 1 4 2 3
Q
Cv 1 2
Q
Cs 3 abaab
Q

Sample Output

4
6
9

解题思路:

相当于插寻trie树上到根节点最大权路径。
修改单点对子树产生贡献。
每次插入/删除一条链。
Dfs序动态维护就好了。
代码1(卡常压缩版100行):
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 typedef long long lnt;
  6 struct trnt{int L,R,fa,rnd,wgt,val,ind,len,mxv,lzt_l,lzt_v;}T[2000010];
  7 struct trie{int ch[26],val;}t[1500010];
  8 int Rt,Rtl,Rtm,Rtr,siz,n,m,Tn,H;
  9 char cmd[100],str[2000010];
 10 int pos[1300010],val[1300010];
 11 inline int Rd(void){
 12     int ans=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch<='9'&&ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans*f;
 14 }
 15 inline void Up(int W){
 16     const int Z=T[W].L,C=T[W].R;
 17     T[W].wgt=1,T[W].mxv=T[W].val;
 18     if(Z)T[W].mxv=std::max(T[W].mxv,T[Z].mxv),
 19     T[W].wgt+=T[Z].wgt;T[Z].fa=W;
 20     if(C)T[W].mxv=std::max(T[W].mxv,T[C].mxv),
 21     T[W].wgt+=T[C].wgt;T[C].fa=W;
 22     return ;
 23 }
 24 inline void A(int W,int v)
 25 {if(!W)return ;T[W].val+=v,T[W].mxv+=v,T[W].lzt_v+=v;return ;}
 26 inline void Al(int W,int l){if(!W)return ;T[W].ind+=l;T[W].lzt_l+=l;return ;}
 27 inline void Dn(int W){
 28     int &Z=T[W].L,&C=T[W].R;
 29     if(T[W].lzt_v){A(Z,T[W].lzt_v);A(C,T[W].lzt_v);T[W].lzt_v=0;}
 30     if(T[W].lzt_l){Al(Z,T[W].lzt_l);Al(C,T[W].lzt_l);T[W].lzt_l=0;}
 31     return ;
 32 }
 33 inline void Rl(int W){if(T[W].fa)Rl(T[W].fa);Dn(W);return ;}
 34 inline void St(int W,int k,int &ll,int &rr){    
 35     int &Z=T[W].L,&C=T[W].R;
 36     if(!W)ll=rr=0;
 37     else{Dn(W);if(T[Z].wgt>=k){rr=W;St(Z,k,ll,Z);}else{ll=W;St(C,k-T[Z].wgt-1,C,rr);}Up(W);}
 38     return ;
 39 }
 40 inline int Mg(int ll,int rr){
 41     if(!ll||!rr)return ll|rr;
 42     if(T[ll].rnd<T[rr].rnd)
 43     {Dn(ll);T[ll].R=Mg(T[ll].R,rr);Up(ll);return ll;}
 44     else{Dn(rr);T[rr].L=Mg(ll,T[rr].L);Up(rr);return rr;}
 45     return 0;
 46 }
 47 inline int Rk(int W){
 48     Rl(W);
 49     int Z=T[W].L,ans=T[Z].wgt+1;
 50     while(W){if(T[T[W].fa].R==W)ans+=T[T[T[W].fa].L].wgt+1;W=T[W].fa;}
 51     return ans;
 52 }
 53 inline void Bc(char *a,int from,int len,int &rt,int v){
 54     int dlt=len-from+1;Rl(rt);
 55     St(Rt,T[rt].ind-1,Rtl,Rtr);
 56     St(Rtr,T[rt].len,Rtm,Rtr);
 57     int dfn=T[rt].ind+T[rt].len-1;
 58     for(int i=from;i<=len;i++){
 59         dfn++;int c=a[i]-'a';t[rt].ch[c]=++siz;T[siz].rnd=rand();
 60         T[siz].val=v;T[siz].wgt=1;T[siz].ind=dfn;T[siz].len=len-i+1;
 61         Rtm=Mg(Rtm,siz);rt=t[rt].ch[c];
 62     }
 63     int ROOT=1;for(int i=1;i<=from;i++){int c=a[i]-'a';T[ROOT].len+=dlt;ROOT=t[ROOT].ch[c];}
 64     Rt=Mg(Mg(Rtl,Rtm),Rtr);St(Rt,Rk(siz),Rtl,Rtr);
 65     if(Rtr)Al(Rtr,dlt);Rt=Mg(Rtl,Rtr);return ;
 66 }
 67 inline void Is(char *a,int &rt){
 68     rt=1;int len=strlen(a+1),v=0;
 69     for(int i=1;i<=len;i++){
 70         int c=a[i]-'a';v+=t[rt].val;
 71         if(!t[rt].ch[c])return Bc(a,i,len,rt,v);rt=t[rt].ch[c];
 72     }return ;
 73 }
 74 inline void Cd(int i,int f){
 75     t[pos[i]].val+=f*val[i];Rl(pos[i]);St(Rt,T[pos[i]].ind-1,Rtl,Rtr);
 76     St(Rtr,T[pos[i]].len,Rtm,Rtr);A(Rtm,val[i]*f);
 77     Rt=Mg(Mg(Rtl,Rtm),Rtr);return ;
 78 }
 79 int main()
 80 {
 81     Tn=Rd();n=Rd();m=Rd();Rt=++siz;T[Rt].rnd=rand();
 82     T[Rt].len=T[Rt].ind=1;
 83     for(int i=1;i<=n;i++)scanf("%s",str+1),Is(str,pos[i]);
 84     for(int i=1;i<=n;i++){val[i]=Rd();if(val[i]<=0)val[i]=0;else Cd(i,1);}
 85     while(m --> 0){
 86         scanf("%s",cmd+1);
 87         if(cmd[1]=='Q')printf("%d
",H=T[Rt].mxv);
 88         if(cmd[2]=='v'){
 89             int x=Rd(),v=Rd();if(Tn==2)v=std::min(1000,v+H%1000);
 90             Cd(x,-1);if(v<=0)v=0;val[x]=v;Cd(x,1);
 91         }
 92         if(cmd[2]=='s'){
 93             int x=Rd();scanf("%s",str+1);
 94             if(Tn==2){int len=strlen(str+1);
 95             for(int i=1;i<=len;i++)str[i]=((int)(str[i]-'a')+H)%26+'a';}
 96             Cd(x,-1);Is(str,pos[x]);Cd(x,1);
 97         }
 98     }
 99     return 0;
100 }
极限版

代码2:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #define lll tr[spc].ls
  6 #define rrr tr[spc].rs
  7 typedef long long lnt;
  8 inline int read(void)
  9 {
 10     int ans=0,f=1;
 11     char ch=getchar();
 12     while(ch<'0'||ch>'9')
 13     {
 14         if(ch=='-')f=-1;
 15         ch=getchar();
 16     }
 17     while(ch>='0'&&ch<='9')
 18     {
 19         ans=ans*10+ch-'0';
 20         ch=getchar();
 21     }
 22     return ans*f;
 23 }
 24 struct trnt{
 25     int ls;
 26     int rs;
 27     int fa;
 28     int rnd;
 29     int wgt;
 30     int val;
 31     int ind;
 32     int len;
 33     int mxv;
 34     int lzt_l;
 35     int lzt_v;
 36 }tr[1000010];
 37 struct trie{
 38     int ch[26];
 39     int val;
 40 }t[1000010];
 41 int root;
 42 int rootl;
 43 int rootm;
 44 int rootr;
 45 int siz;
 46 int n,m;
 47 int testno;
 48 int lastans;
 49 char cmd[100];
 50 int pos[100010];
 51 int val[100010];
 52 char str[1000010];
 53 inline void pushup(int spc)
 54 {
 55     tr[spc].wgt=1;
 56     tr[spc].mxv=tr[spc].val;
 57     if(lll)
 58     {
 59         tr[spc].mxv=std::max(tr[spc].mxv,tr[lll].mxv);
 60         tr[spc].wgt+=tr[lll].wgt;
 61         tr[lll].fa=spc;
 62     }
 63     if(rrr)
 64     {
 65         tr[spc].mxv=std::max(tr[spc].mxv,tr[rrr].mxv);
 66         tr[spc].wgt+=tr[rrr].wgt;
 67         tr[rrr].fa=spc;
 68     }
 69     return ;
 70 }
 71 inline void ADD(int spc,int v)
 72 {
 73     if(!spc)return ;
 74     tr[spc].val+=v;
 75     tr[spc].mxv+=v;
 76     tr[spc].lzt_v+=v;
 77     return ;
 78 }
 79 inline void ADDLEN(int spc,int l)
 80 {
 81     if(!spc)return ;
 82     tr[spc].ind+=l;
 83     tr[spc].lzt_l+=l;
 84     return ;
 85 }
 86 inline void pushdown(int spc)
 87 {
 88     if(tr[spc].lzt_v)
 89     {
 90         ADD(lll,tr[spc].lzt_v);
 91         ADD(rrr,tr[spc].lzt_v);
 92         tr[spc].lzt_v=0;
 93     }
 94     if(tr[spc].lzt_l)
 95     {
 96         ADDLEN(lll,tr[spc].lzt_l);
 97         ADDLEN(rrr,tr[spc].lzt_l);
 98         tr[spc].lzt_l=0;
 99     }
100     return ;
101 }
102 void recal(int spc)
103 {
104     if(tr[spc].fa)recal(tr[spc].fa);
105     pushdown(spc);
106     return ;
107 }
108 void split(int spc,int k,int &ll,int &rr)
109 {
110     if(!spc)ll=rr=0;
111     else{
112         pushdown(spc);
113         if(tr[lll].wgt>=k)
114         {
115             rr=spc;
116             split(lll,k,ll,lll);
117         }else{
118             ll=spc;
119             split(rrr,k-tr[lll].wgt-1,rrr,rr);
120         }
121         pushup(spc);
122     }
123     return ;
124 }
125 int merge(int ll,int rr)
126 {
127     if(!ll||!rr)return ll|rr;
128     if(tr[ll].rnd<tr[rr].rnd)
129     {
130         pushdown(ll);
131         tr[ll].rs=merge(tr[ll].rs,rr);
132         pushup(ll);
133         return ll;
134     }else{
135         pushdown(rr);
136         tr[rr].ls=merge(ll,tr[rr].ls);
137         pushup(rr);
138         return rr;
139     }
140     return 0;
141 }
142 int rank(int spc)
143 {
144     recal(spc);
145     int ans=tr[lll].wgt+1;
146     while(spc)
147     {
148         if(tr[tr[spc].fa].rs==spc)ans+=tr[tr[tr[spc].fa].ls].wgt+1;
149         spc=tr[spc].fa;
150     }
151     return ans;
152 }
153 void build_chain(char *a,int from,int len,int &rt,int v)
154 {
155     int dlt=len-from+1;
156     int ROOT=1;
157     recal(rt);
158     split(root,tr[rt].ind-1,rootl,rootr);
159     split(rootr,tr[rt].len,rootm,rootr);
160     int dfn=tr[rt].ind+tr[rt].len-1;
161     for(int i=from;i<=len;i++)
162     {
163         dfn++;
164         int c=a[i]-'a';
165         t[rt].ch[c]=++siz;
166         tr[siz].rnd=rand();
167         tr[siz].val=v;
168         tr[siz].wgt=1;
169         tr[siz].ind=dfn;
170         tr[siz].len=len-i+1;
171         rootm=merge(rootm,siz);
172         rt=t[rt].ch[c];
173     }
174     for(int i=1;i<=from;i++)
175     {
176         int c=a[i]-'a';
177         tr[ROOT].len+=dlt;
178         ROOT=t[ROOT].ch[c];
179     }
180     root=merge(merge(rootl,rootm),rootr);
181     split(root,rank(siz),rootl,rootr);
182     if(rootr)ADDLEN(rootr,dlt);
183     root=merge(rootl,rootr);
184     return ;
185 }
186 void insert(char *a,int &rt)
187 {
188     int len=strlen(a+1);
189     rt=1;
190     int v=0;
191     for(int i=1;i<=len;i++)
192     {
193         int c=a[i]-'a';
194         v+=t[rt].val;
195         if(!t[rt].ch[c])return build_chain(a,i,len,rt,v);
196         rt=t[rt].ch[c];
197     }
198     return ;
199 }
200 void change_dfn(int i,int f)
201 {
202     t[pos[i]].val+=f*val[i];
203     recal(pos[i]);
204     split(root,tr[pos[i]].ind-1,rootl,rootr);
205     split(rootr,tr[pos[i]].len,rootm,rootr);
206     ADD(rootm,val[i]*f);
207     root=merge(merge(rootl,rootm),rootr);
208     return ;
209 }
210 int main()
211 {
212     srand(17);
213     testno=read();
214     n=read();m=read();
215     root=++siz;
216     tr[root].rnd=rand();
217     tr[root].len=tr[root].ind=1;
218     for(int i=1;i<=n;i++)
219     {
220         scanf("%s",str+1);
221         insert(str,pos[i]);
222     }
223     for(int i=1;i<=n;i++)
224     {
225         val[i]=read();
226         if(val[i]<=0)val[i]=0;
227         else change_dfn(i,1);
228     }
229     while(m --> 0)
230     {
231         scanf("%s",cmd+1);
232         if(cmd[1]=='Q')
233             printf("%d
",lastans=tr[root].mxv);
234         if(cmd[2]=='v')
235         {
236             int x=read(),v=read();
237             if(testno==2)v=std::min(1000,v+lastans%1000);
238             change_dfn(x,-1);
239             if(v<=0)v=0;
240             val[x]=v;
241             change_dfn(x,1);
242         }
243         if(cmd[2]=='s')
244         {
245             int x=read();
246             scanf("%s",str+1);
247             if(testno==2)
248             {
249                 int len=strlen(str+1);
250                 for(int i=1;i<=len;i++)
251                     str[i]=((int)(str[i]-'a')+lastans)%26+'a';
252             }
253             change_dfn(x,-1);
254             insert(str,pos[x]);
255             change_dfn(x,1);
256         }
257     }
258     return 0;
259 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/10462938.html