• [HNOI 2016] 树


    传送门

    Solution

    这个才是真的"树套树"嘛

    题目看上去就很暴力,而实现起来更暴力

    • 加进去的子树显然看成一个点,在建一棵新的树
    • 两个树都要树剖
    • 因为涉及到在原树上找点的问题,而我们知道一个点在某个子树内的排名,所以只好用主席树了

    注意会爆long long!

    因为调到生无可恋,只好加了这句

    #define int long long
    

    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define int long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    #define reg register
    #define MN 100005
    //模板树中的操作 
    struct edge{int to,nex;}e[MN<<1];
    int hr[MN],en;
    inline void ins(int f,int t)
    {
        e[++en]=(edge){t,hr[f]};hr[f]=en;
        e[++en]=(edge){f,hr[t]};hr[t]=en;
    }
    int N,deep[MN],par[MN],Top[MN],Siz[MN],Mx[MN],dfn[MN],fdfn[MN],dind;
    inline void dfs1(int x,int f)
    {
        deep[x]=deep[par[x]=f]+1;Siz[x]=1;
        for(reg int i=hr[x];i;i=e[i].nex)if(f^e[i].to)
            dfs1(e[i].to,x),Siz[e[i].to]>Siz[Mx[x]]?Mx[x]=e[i].to:0,Siz[x]+=Siz[e[i].to];
    }
    inline void dfs2(int x,int tp)
    {
        dfn[x]=++dind;fdfn[dind]=x;Top[x]=tp;if(Mx[x]) dfs2(Mx[x],tp);
        for(reg int i=hr[x];i;i=e[i].nex)if((par[x]^e[i].to)&&(Mx[x]^e[i].to))
            dfs2(e[i].to,e[i].to);
    }
    inline ll Getdis(int x,int y)
    {
        ll res=deep[x]+deep[y];
        while(Top[x]^Top[y])
        {
            if(deep[Top[x]]>deep[Top[y]]) x=par[Top[x]];
            else y=par[Top[y]];
        }
        return res-2*min(deep[x],deep[y]);
    }
    #define mid ((l+r)>>1)
    int sz,t[MN*20],ls[MN*20],rs[MN*20],rt[MN];
    void Modify(int &rt,int ori,int l,int r,int x)
    {
        rt=++sz;ls[rt]=ls[ori];rs[rt]=rs[ori];t[rt]=t[ori]+1;
        if(l==r) return;
        if(x<=mid) Modify(ls[rt],ls[ori],l,mid,x);
        else Modify(rs[rt],rs[ori],mid+1,r,x);
    }
    inline int init()
    {
        for(reg int i=1;i<=N;++i) Modify(rt[i],rt[i-1],1,N,fdfn[i]);
    }
    inline int Query(int rt1,int rt2,int l,int r,int k)
    {
        if(l==r) return l;
        if(t[ls[rt2]]-t[ls[rt1]]>=k) return Query(ls[rt1],ls[rt2],l,mid,k);
        else return Query(rs[rt1],rs[rt2],mid+1,r,k-(t[ls[rt2]]-t[ls[rt1]]));
    }
    inline int point(int k,int x)
    {
        return Query(rt[dfn[x]-1],rt[dfn[x]+Siz[x]-1],1,N,k);
    }
    #undef mid
    //鲲树的操作
    int root[MN],M;
    ll a[MN],from[MN];
    edge E[MN<<1];int En,Hr[MN];
    inline void Ins(int f,int t)
    {
        E[++En]=(edge){t,Hr[f]};Hr[f]=En;
        E[++En]=(edge){f,Hr[t]};Hr[t]=En;
    }
    inline int get(ll x){return std::lower_bound(a+1,a+M+2,x)-a;}
    inline int getrk(ll x,int y){return x-a[y-1];}
    int dep[MN],siz[MN],mx[MN],top[MN],fa[MN];
    ll dis_tp[MN];
    inline void Dfs1(int x,int f)
    {
        dep[x]=dep[fa[x]=f]+1,siz[x]=1;
        for(reg int i=Hr[x];i;i=E[i].nex)if(f^E[i].to)
            Dfs1(E[i].to,x),siz[E[i].to]>siz[mx[x]]?mx[x]=E[i].to:0,siz[x]+=siz[E[i].to];
    }
    inline void Dfs2(int x,int tp)
    {
        if(x==tp) dis_tp[x]=0;
        else dis_tp[x]=1ll*dis_tp[fa[x]]+1ll+1ll*deep[from[x]]-1ll*deep[root[fa[x]]];
        top[x]=tp;
        if(mx[x]) Dfs2(mx[x],tp);
        for(reg int i=Hr[x];i;i=E[i].nex)if((fa[x]^E[i].to)&&(mx[x]^E[i].to))
            Dfs2(E[i].to,E[i].to);
    }
    void que(ll x,ll y)
    {
        int X=get(x),Y=get(y);
        if(X==Y)
        {
            std::cout<<Getdis(x=point(getrk(x,X),root[X]),y=point(getrk(y,Y),root[Y]))<<std::endl;
            return;
        }
        ll ans=0ll;x=point(getrk(x,X),root[X]);y=point(getrk(y,Y),root[Y]);
        while(top[X]^top[Y])
        {
            if(dep[top[X]]>dep[top[Y]])
            {
                ans+=1ll*(deep[x]-deep[root[X]]);
                ans+=1ll*dis_tp[X]+1ll;x=from[top[X]];X=fa[top[X]];
            }
            else
            {
                ans+=1ll*(deep[y]-deep[root[Y]]);
                ans+=1ll*dis_tp[Y]+1ll;y=from[top[Y]];Y=fa[top[Y]];
            }
        }
        if(dep[X]^dep[Y])
        {
            if(dep[X]>dep[Y]) ans+=1ll*dis_tp[X]-1ll*dis_tp[Y]+1ll*(deep[x]-deep[root[X]])-1ll*(deep[from[mx[Y]]]-deep[root[Y]]),x=from[mx[Y]];
            else ans+=1ll*dis_tp[Y]-1ll*dis_tp[X]-1ll*(deep[from[mx[X]]]-deep[root[X]])+1ll*(deep[y]-deep[root[Y]]),y=from[mx[X]];
        }
        ans+=1ll*Getdis(x,y);std::cout<<ans<<std::endl; 
    }
    main()
    {
        register int i,Q;register ll x,y;
        N=read();M=read();Q=read();
        for(i=1;i<N;++i) x=read(),ins(x,read());
        dfs1(1,0);dfs2(1,1);init();root[1]=1;
        for(a[1]=N,i=2;i<=M+1;++i) root[i]=read(),from[i]=read(),a[i]=a[i-1]+Siz[root[i]];
        for(i=2;i<=M+1;++i) Ins(x=get(from[i]),i),from[i]=point(getrk(from[i],x),root[x]);
        Dfs1(1,0);Dfs2(1,1);
        while(Q--) x=read(),y=read(),que(x,y);
        return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    CodeFirst进行数据迁移之添加字段
    .NET程序优化
    DataRead 和DataSet区别
    WCF、WebAPI、WCFREST、WebService之间的区别
    centos6.7下安装配置vnc
    Centos 6.5 优化 一些基础优化和安全设置
    Elasticsearch 检索
    ElasticSearch 5.0.1 java API操作
    Elasticsearch5.0.1 + Kibana5.0.1 + IK 5.0.1安装记录
    Spring的注解@Qualifier小结
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10146489.html
Copyright © 2020-2023  润新知