CF519E

[LCA到x和LCA到y的距离相等且x,y不是同一个点\ ans=n-siz[x]-siz[y]\ LCA到x和LCA到y的距离不相等,且分别为a,b\ (1)a+b为奇数,a-b一定为奇数\ (2)a+b偶数,令a>b,a上必有一点的LCA-(a-b)/2到x,y距离相等\ 设这个点为P,以P为根的子树结点-P到x的结点数+1=到x,y距离相等的点数\ x=y时ans=n ]

#include<cstdio>
#include<iostream>
using namespace std;
const int N = 1e5 + 5;
int n,m,fa[N][20],dep[N],siz[N];
struct edge{int to,next;}e[N<<1]; int head[N],tot;
inline void add(int u,int v){e[++tot] = (edge){v,head[u]}; head[u] = tot;}
void dfs(int x,int f){
	fa[x][0] = f; siz[x] = 1;
	for(int i = 1;i < 20;++i) fa[x][i] = fa[fa[x][i-1]][i-1];
	dep[x] = dep[f] + 1;
	for(int i = head[x];i;i = e[i].next){
		int v = e[i].to;
		if(v == f) continue;
		dfs(v,x); siz[x] += siz[v];
	}
}
int LCA(int u,int v) {
    if(dep[u]>dep[v]) 
		swap(u,v);
    
    for(int i=19;i>=0;i--)
        if(dep[fa[v][i]] >= dep[u])  v = fa[v][i];

    if(u==v) 
		return u;
    for(int i=19;i>=0;i--) {
        if(fa[u][i]==fa[v][i]) 
			continue;
        u = fa[u][i];
        v = fa[v][i];
    }
    return fa[u][0];
}
int jump_up(int u,int k) {
    int i = 0;
    while(k) {
        if(k&1) u = fa[u][i];
        k>>=1;
        i++;
    }
    return u;
}
inline int read(){
	int x = 0;char c = getchar();
	while(!isdigit(c))c = getchar();
	while(isdigit(c))x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
	return x;
}
int main(){
	n = read(); int x,y;
	for(int i = 1;i < n;++i){
		x = read(); y = read();
		add(x,y); add(y,x);
	}
	m = read(); dfs(1,0);
	for(int i = 1;i <= m;++i){
		x = read(); y = read();
		int lca = LCA(x,y);
		if(x == y) printf("%d
",n);
		else if(dep[x] == dep[y]){
			int a =jump_up(x,dep[x]-dep[lca]-1);
            int b = jump_up(y,dep[y]-dep[lca]-1);
            printf("%d
",n - siz[a] - siz[b]);
		}
		else{
			 int d = dep[x]+dep[y] -2*dep[lca];
            if(d & 1) puts("0");
            else {
                if(dep[x]>dep[y]) swap(x,y);
                int b = jump_up(y,d/2-1);
                int a = fa[b][0];
                printf("%d
",siz[a] - siz[b]);
		}
	}
}
}
原文地址:https://www.cnblogs.com/shikeyu/p/13647788.html