[10.2模拟] tree
题意:给你一棵树,m次询问,每次询问(a,b),即a和b是否在一条链上
题解:
树上倍增
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define RG register
#define N 200010
using namespace std;
int n,qu,e_num;
int nxt[N*2],to[N*2],h[N],siz[N],dep[N],fa[N][22];
inline int gi() {
int x=0,o=1; char ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') o=-1,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return o*x;
}
inline void add(int x, int y) {
nxt[++e_num]=h[x],to[e_num]=y,h[x]=e_num;
}
inline int find(int y, int x) {
for(int j=20; j>=0; j--) {
if(dep[fa[y][j]]>dep[x] && fa[y][j]) y=fa[y][j];
}
return y;
}
inline void dfs(int u) {
siz[u]=1;
for(int i=h[u]; i; i=nxt[i]) {
int v=to[i];
if(v==fa[u][0]) continue;
fa[v][0]=u,dep[v]=dep[u]+1;
dfs(v);
siz[u]+=siz[v];
}
}
int main() {
n=gi(),qu=gi();
for(RG int i=1; i<n; i++) {
int x=gi(),y=gi();
add(x,y),add(y,x);
}
dep[1]=1;
dfs(1);
for(int j=1; j<=20; j++)
for(int i=1; i<=n; i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
for(int i=1; i<=qu; i++) {
int x=gi(),y=gi(),z;
if(dep[x]>dep[y]) swap(x,y);
z=find(y,x);
if(fa[z][0]!=x) printf("%d\n", siz[x]+siz[y]);
else printf("%d\n", siz[y]+n-siz[z]);
}
return 0;
}