• BZOJ2690 : 字符串游戏


    离线算法:

    先将所有涉及到的串建成字典树,然后用线段树维护dfs序,时间复杂度$O(mlog L)$。

    在线算法:

    用替罪羊树动态维护Trie树的dfs序即可,时间复杂度$O(Llog 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
    ",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
    ",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;
    }
    

      

  • 相关阅读:
    Js获取或计算时间的相关操作
    SqlServer删除表中重复的记录并保留一条
    获取js文件后的参数
    谷歌浏览器官方下载地址
    ionic项目中实现发短信和打电话
    ui-router传递参数
    ng-options用法详解
    html5 localStorage(本地存储)
    cordova插件之Local Notification(本地通知)
    AngularJS $http service
  • 原文地址:https://www.cnblogs.com/clrs97/p/4872958.html
Copyright © 2020-2023  润新知