[主席树维护HASH && SET维护DFS序] Codechef. Walks on the binary tree

来源:互联网 发布:七个魂器都是什么 知乎 编辑:程序博客网 时间:2024/05/17 07:26

传送门

每次加一个串 x 会增加 n-max{LCP(x,i)},因为是树上,max{LCP(x,i)}就肯定是dfs序中跟它相邻的点,也就是它们的lca深度最深。
那么就用set维护一下dfs序,比较的话,用主席树维护hash

#include <cstdio>#include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#define fi first#define se secondusing namespace std;typedef unsigned long long ll;typedef pair<ll,ll> pari;const int N=100010,P1=1e9+7,P2=1e9+9;const pari base={7,29};int n,q,t,cnt,g,rt[N*50],ls[N*50],rs[N*50],tag[N*50],tot[N*50];pari pw[N],v[N*50],p[N];pari operator +(const pari &a,const pari &b){ return pari((a.fi+b.fi)%P1,(a.se+b.se)%P2); }pari operator -(const pari &a,const pari &b){ return pari((a.fi+P1-b.fi)%P1,(a.se+P2-b.se)%P2); }pari operator *(const pari &a,const pari &b){ return pari((a.fi*b.fi)%P1,(a.se*b.se)%P2); }inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void rea(int &x){  char c=nc(); x=0;  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());}inline void set1(int &g,int l,int r){  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k];  tot[g]=r-l+1; v[g]=p[r-l]; tag[g]=1;}inline void set0(int &g,int l,int r){  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k];  tot[g]=0; v[g]={0,0}; tag[g]=0;}inline void Push(int &g,int L,int R){  if(~tag[g]){    int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k];    int mid=L+R>>1;    if(tag[g])      set1(ls[g],L,mid),set1(rs[g],mid+1,R);    else      set0(ls[g],L,mid),set0(rs[g],mid+1,R);    tag[g]=-1;  }}inline bool cmp(int &a,int &b,int l,int r){  Push(a,l,r); Push(b,l,r);  if(l==r) return v[a]<v[b];;  int mid=l+r>>1;  if(v[ls[a]]==v[ls[b]])    return cmp(rs[a],rs[b],mid+1,r);  else    return cmp(ls[a],ls[b],l,mid);}struct u{  int x;  friend bool operator ==(u a,u b){    return v[a.x]==v[b.x];  }  friend bool operator <(u a,u b){    if(v[a.x]==v[b.x]) return false;    return cmp(a.x,b.x,1,n);  }};set<u> S;long long ans;int Find(int &g,int l,int r,int L,int R){  if(!g) return r;  if(L==R) return tot[g]?-1:L;  int mid=L+R>>1; Push(g,L,R);  if(l==L && r==R){    if(tot[rs[g]]!=R-mid) return Find(rs[g],mid+1,r,mid+1,R);    return Find(ls[g],l,mid,L,mid);  }  if(r<=mid) return Find(ls[g],l,r,L,mid);  else if(l>mid) return Find(rs[g],l,r,mid+1,R);  int ret=Find(rs[g],mid+1,r,mid+1,R);  if(~ret) return ret;  return Find(ls[g],l,mid,L,mid);}inline void Up(int g,int l){  v[g]=v[ls[g]]*pw[l]+v[rs[g]];  tot[g]=tot[ls[g]]+tot[rs[g]];}void Cover(int &g,int l,int r,int L,int R){  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k];  if(l==L && r==R) return set0(g,L,R);  int mid=L+R>>1; Push(g,L,R);  if(r<=mid) Cover(ls[g],l,r,L,mid);  else if(l>mid) Cover(rs[g],l,r,mid+1,R);  else Cover(ls[g],l,mid,L,mid),Cover(rs[g],mid+1,r,mid+1,R);  Up(g,R-mid);}void Modify(int &g,int x,int L,int R){  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; tot[g]=tot[k]; v[g]=v[k];  if(L==R) return set1(g,L,R);  int mid=L+R>>1; Push(g,L,R);  if(x<=mid) Modify(ls[g],x,L,mid);else Modify(rs[g],x,mid+1,R);  Up(g,R-mid);}inline int Same(int x,int y){  if(v[x]==v[y]) return n+1;  int l=1,r=n;  while(l<r){    int mid=l+r>>1;    if(v[ls[x]]==v[ls[y]])      Push(rs[x],mid+1,r),Push(rs[y],mid+1,r),x=rs[x],y=rs[y],l=mid+1;    else      Push(ls[x],l,mid),Push(ls[y],l,mid),x=ls[x],y=ls[y],r=mid;  }  return l;}int main(){  rea(t);  pw[0]=p[0]={1,1}; for(int i=1;i<=100000;i++) p[i]=p[i-1]+(pw[i]=pw[i-1]*base);  while(t--){    rea(n); rea(q); S.clear();    memset(tag,-1,sizeof(tag)); g=0; ans=0;    for(int i=1;i<=n;i++) rt[i]=0; cnt=0;    for(int i=1;i<=q;i++){      if(i==4)    int ssss=0;      char c; while((c=nc())!='?' && c!='!');      if(c=='?') printf("%lld\n",max(ans,1LL));      else{    int x; rea(x); x=n-x;    rt[g+1]=rt[g]; g++;    int pos=Find(rt[g],1,x,1,n);    if(~pos){      if(pos+1<=x) Cover(rt[g],pos+1,x,1,n);      Modify(rt[g],pos,1,n);    }    else Cover(rt[g],1,x,1,n);    Push(rt[g],1,n);    if(S.find(u{rt[g]})!=S.end()){      continue;     }    set<u>::iterator IT=S.insert(u{rt[g]}).first;    int cur=0; ans+=n+1;    if(IT!=S.begin())      IT--,cur=Same(IT->x,rt[g]),IT++;    IT++;    if(IT!=S.end())      cur=max(cur,Same(IT->x,rt[g]));    ans-=cur;      }    }  }  return 0;}
阅读全文
0 0
原创粉丝点击