【COGS2622】后缀平衡树

这是个后缀平衡树的裸题。。。。

然后傻逼的我调了一下午。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e5+10;
const int bas=31;
int hs[N],M[N];
int n,len,ans,Ans[N];
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
struct Suffix_Balanced_ScapeGoat_Tree{
    int lx[N],rx[N],rt,size[N],s[N],cnt,Q[N],tail;
    ll tag[N];
    int get(int i,int l){return hs[i]-hs[i-l]*M[l];}
    int qlcp(int x,int y){
        int l=0,r=min(x,y);
        while(l<r){
            int mid=(l+r)>>1;
            if(get(x,mid+1)==get(y,mid+1))l=mid+1;else r=mid;
        }
        return l;
    }
    inline bool cmp(int x,int y){int l=qlcp(x,y);return s[x-l]<s[y-l];}
    inline int merge(int x,int y){
        if(!x||!y)return x|y;
        if(size[x]>size[y]){size[x]+=size[y];rx[x]=merge(rx[x],y);return x;}
        else{size[y]+=size[x];lx[y]=merge(x,lx[y]);return y;}
    }
    inline int build(int ls,int rs,ll l,ll r){
        if(ls>rs)return 0;
        int mid=(ls+rs)>>1;ll midv=(l+r)>>1;int x=Q[mid];tag[x]=midv;
        lx[x]=build(ls,mid-1,l,midv);rx[x]=build(mid+1,rs,midv,r);
        size[x]=rs-ls+1;return x;
    }
    inline void dfs(int x){if(lx[x])dfs(lx[x]);Q[++tail]=x;if(rx[x])dfs(rx[x]);}
    inline int rebuild(int x,ll l,ll r){
        tail=0;dfs(x);return build(1,tail,l,r);
    }
    inline int ins(int x,ll l,ll r,int val){
        if(!x){
            size[++cnt]=1;lx[cnt]=rx[cnt]=0;tag[cnt]=(l+r)>>1;
            return cnt;
        }
        size[x]++;
        if(cmp(x,val)){
            rx[x]=ins(rx[x],tag[x],r,val);
            if(size[rx[x]]>0.65*size[x])x=rebuild(x,l,r);
        }
        else{
            lx[x]=ins(lx[x],l,tag[x],val);
            if(size[lx[x]]>0.65*size[x])x=rebuild(x,l,r);
        }
        return x;
    }
    inline int del(int x,int val){
        if(x==val)return merge(lx[x],rx[x]);
        size[x]--;
        if(tag[x]<tag[val])rx[x]=del(rx[x],val);
        else lx[x]=del(lx[x],val);
        return x;
    }
    inline int queryrk(int key){
        int x=rt,ans=0;
        while(1){
            int i=size[lx[x]]+1;
            if(key==x)return ans+i;
            if(tag[x]<tag[key])x=rx[x],ans+=i;else x=lx[x];
        }
    }
    inline int find(int key){
        int x=rt;
        while(1){
            int i=size[lx[x]]+1;
            if(key==i)return x;
            if(key>i)x=rx[x],key-=i;else x=lx[x];
        }
    }
    inline void del(int x){
        int rk=queryrk(x),y=find(rk-1),z=find(rk+1);
        ans-=qlcp(x,y)+qlcp(x,z)-qlcp(y,z);
        rt=del(rt,x);cnt--;len--;
    }
    inline void ins(int x){
        s[++len]=x;hs[len]=hs[len-1]*bas+x;
        rt=ins(rt,0,1LL<<62,len);
        if(len<3)return;
        int rk=queryrk(len),y=find(rk-1),z=find(rk+1);
        ans+=qlcp(len,y)+qlcp(len,z)-qlcp(y,z);
    }
}T;
char str[N];
struct Edge{int u,v,next;}G[N<<1];int head[N],tot=0;
inline void addedge(int u,int v){
    G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot;
    G[++tot].u=v;G[tot].v=u;G[tot].next=head[v];head[v]=tot;
}
inline void dfs(int u,int fa){
    T.ins(str[u]-'a'+1);Ans[u]=(len-1)*(len-2)/2-ans;
    for(int i=head[u];i;i=G[i].next){
        if(G[i].v!=fa)dfs(G[i].v,u);
    }
    T.del(len);
}
int main(){
    freopen("balsuffix.in","r",stdin);
    freopen("balsuffix.out","w",stdout);
    M[0]=1;
    for(int i=1;i<N;i++)M[i]=M[i-1]*bas;
    T.ins(27);T.ins(0);int T=read();
    while(T--){
        n=read();for(int i=1;i<=n;i++)head[i]=0;tot=0;
        for(int i=1;i<n;i++){
            int u=read(),v=read();addedge(u,v);
        }
        scanf("%s",str+1);
        dfs(1,0);
        for(int i=1;i<=n;i++)printf("%d\n",Ans[i]);
    }
}

 

posted @ 2017-08-29 16:12  zcysky  阅读(302)  评论(0编辑  收藏  举报