BZOJ2690 : 字串游戲

Claris發表於2015-10-12

離線演算法:

先將所有涉及到的串建成字典樹,然後用線段樹維護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;
}

  

相關文章