zoukankan      html  css  js  c++  java
  • 【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
    ",Ans[i]);
        }
    }
  • 相关阅读:
    小程序(1)
    手机端放在线条中间的标题
    不定长度导航的两端对齐
    扇形导航菜单
    个性搜索框
    javascript数组原型方法
    jquery插件开发的demo
    监听表单中的内容变化
    mui中的关闭页面的几种方法
    css之伪类选择器:before :after(::before ::after)
  • 原文地址:https://www.cnblogs.com/zcysky/p/7448811.html
Copyright © 2011-2022 走看看