• cf519E


    传送门

    多组询问,问到树上两个点x,y距离相等的点的个数。

    倍增求lca.

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<ctime>
    const int maxn=1e5+299;
    typedef long long LL;
    using namespace std;
    int n,m,ecnt,fir[maxn],nxt[maxn<<1],to[maxn<<1],f[maxn][21],R[maxn],sz[maxn];;
    void add(int u,int v) {
        nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
        nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
    }
    void dfs(int x,int fa) {
        R[x]=R[fa]+1;
        f[x][0]=fa; 
        sz[x]=1;
        for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
            dfs(to[i],x);
            sz[x]+=sz[to[i]];
        }
    }
    void make_st() {
        for(int i=1;i<=20;i++)
            for(int j=1;j<=n;j++) 
                f[j][i]=f[f[j][i-1]][i-1];
    }
    int lca(int x,int y) {
        if(R[x]<R[y]) swap(x,y);
        for(int i=20;i>=0;i--) 
            if(R[f[x][i]]>=R[y]) x=f[x][i];
        if(x==y) return x;
        for(int i=20;i>=0;i--) 
            if(f[x][i]!=f[y][i]) {
                x=f[x][i];
                y=f[y][i];
            }
        return f[x][0];
    }
    int cal(int x,int y) {
        if(x==y) return sz[1];
        int z=lca(x,y);
        if(R[x]==R[y]) {
            for(int i=20;i>=0;i--) 
                if(f[x][i]!=f[y][i]) {
                x=f[x][i];
                y=f[y][i];
                }
            return sz[1]-sz[x]-sz[y];
        }
        int l=R[x]-R[z]+R[y]-R[z];
        if(l&1) return 0; l>>=1;
        if(R[x]<R[y]) swap(x,y);
        l=R[x]-R[z]-l+1;
        for(int i=20;i>=0;i--) 
            if(R[f[x][i]]&&R[f[x][i]]-R[z]>=l)
                x=f[x][i];
        return sz[f[x][0]]-sz[x];
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        dfs(1,0);
        make_st();
        scanf("%d",&m);
        for(int i=1;i<=m;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",cal(x,y));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    参考资料来自 懒兔子 的公众号
    Etcd
    zookeeper 杂记
    十二五
    防火墙
    APScheduler
    docker管理工具protainer
    java学习笔记
    linux学习笔记1
    [POI2007]ZAP-Queries
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7622740.html
Copyright © 2020-2023  润新知