CF 519E(树上倍增求lca)

 

传送门:A and B and Lecture Rooms

题意:给定一棵树,每次询问到达点u,v距离相等的点有多少个。

分析:按情况考虑:

1.abs(deep[u]-deep[v])%2==1时,必定不存在到达u,v距离相等的点。

2.如果deep[u]==deep[v]时,ans=n-num[lca(u,v)u在的儿子树]-num[lca(u,v)v在的儿子树]。

3.如果deep[u]!=deep[v]时,在u到v的路径中找出到达u,v相等的节点x,则ans=num[x]-num[u在的x儿子树].

#include <algorithm>

#include <iostream>

#include <cstring>

#include <cstdlib>

#include <cstdio>

#include <queue>

#include <map>

#define N 200010

#define LL long long

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

using namespace std;

struct edge

{

    int v,next;

    edge() {}

    edge(int v,int next):v(v),next(next) {}

} e[N];

int head[N],tot;

int num[N],deep[N];

int fa[N][20];

void init()

{

    memset(head,-1,sizeof(head));

    tot=0;

}

void addedge(int u,int v)

{

    e[tot]=edge(v,head[u]);

    head[u]=tot++;

}

void dfs(int x,int f)

{

    for(int i=1; i<20; i++)

    {

        if(deep[x]<(1<<i))break;

        fa[x][i]=fa[fa[x][i-1]][i-1];

    }

    for(int i=head[x]; ~i; i=e[i].next)

    {

        int v=e[i].v;

        if(v==f)continue;

        fa[v][0]=x;

        deep[v]=deep[x]+1;

        dfs(v,x);

        num[x]+=num[v];

    }

}

int lca(int x,int y)

{

    if(deep[x]<deep[y])swap(x,y);

    int t=deep[x]-deep[y];

    for(int i=0; i<=19; i++)

        if((1<<i)&t)x=fa[x][i];

    for(int i=19; i>=0; i--)

    {

        if(fa[x][i]!=fa[y][i])

        {

            x=fa[x][i];

            y=fa[y][i];

        }

    }

    if(x==y)return x;

    return fa[x][0];

}

int main()

{

    int n,m;

    while(scanf("%d",&n)>0)

    {

        init();

        for(int i=1; i<n; i++)

        {

            int u,v;

            scanf("%d%d",&u,&v);

            addedge(u,v);

            addedge(v,u);

        }

        for(int i=1;i<=n;i++)num[i]=1;

        deep[1]=1;

        dfs(1,0);

        scanf("%d",&m);

        while(m--)

        {

            int x,y;

            scanf("%d%d", &x,&y);

            if(deep[x]<deep[y])swap(x,y);

            if((deep[x]-deep[y])&1) printf("0\n");

            else

            {

                int xy=lca(x, y),tx=x;

                int t=(deep[x]+deep[y]-2*deep[xy])/2-1;

                for(int i=0;i<20;i++)if(t&(1<<i))x=fa[x][i];

                if(deep[tx]==deep[y])

                {

                    t=deep[y]-deep[xy]-1;

                    for(int i=0;i<20;i++)if(t&(1<<i))y=fa[y][i];

                    printf("%d\n",n-num[x]-num[y]);

                }

                else printf("%d\n", num[fa[x][0]]-num[x]);

            }

        }

    }

}
View Code

 

你可能感兴趣的:(ca)