多组询问,问到树上两个点x,y距离相等的点的个数。
倍增求lca.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//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;
}