• 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 }
  • 相关阅读:
    管道及有名管道(pipe与FIFO)
    详细介绍Linux重定向的使用
    Emacs文件和目录操作模式Dired
    exec家族函数
    Seven file types of Unix system(4.3)
    va_list、va_start、va_arg、va_end的原理与使用
    const int*和int const*的区别
    asp.net 文件加载错误
    终于有了属于自己的家,哈哈,很高兴~~
    难得的一场雪
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10462938.html
Copyright © 2020-2023  润新知