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
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
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\n",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\n",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 }