题意:给定一颗树,点10^5,询问10^5,每次询问给出两个点,求树上有多少点到这两个点的距离相同。
解法:建立倍增LCA,然后每次询问考虑如下,1)u==v,显然答案是n。2)u到v的距离为奇数(可通过LCA求出),显然案
为0。3)u和v的深度相同,那么答案就是n-lca偏向u的子树大小-lca偏向v的子树大小。4)u和v的深度不同,设v的深度大,
答案就是lca的子树大小-lca偏向v的子树大小。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 100005 #define maxm 200005 #define eps 1e-7i #define mod 1000000007 #define INF 0x3f3f3f3f #define PI (acos(-1.0)) #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R #define pii pair<int, int> #pragma comment(linker, "/STACK:16777216") typedef long long LL; typedef unsigned long long ULL; //typedef int LL; using namespace std; LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} // head struct Edge { int v; Edge *next; }*H[maxn], *edges, E[maxm]; int anc[maxn][20]; int size[maxn]; int dep[maxn]; int n, m; const int M = 20; void init() { edges = E; memset(H, 0, sizeof H); } void addedges(int u, int v) { edges->v = v; edges->next = H[u]; H[u] = edges++; } void read() { int u, v; scanf("%d", &n); for(int i = 1; i < n; i++) { scanf("%d%d", &u, &v); addedges(u, v); addedges(v, u); } scanf("%d", &m); } void dfs(int u, int fa) { size[u] = 1, anc[u][0] = fa; for(Edge *e = H[u]; e; e = e->next) { int v = e->v; if(v == fa) continue; dep[v] = dep[u] + 1; dfs(v, u); size[u] += size[v]; } } int to(int u, int d) { for(int i = M - 1; i >= 0; i--) if(dep[anc[u][i]] >= d) u = anc[u][i]; return u; } int lca(int u, int v) { if(dep[u] < dep[v]) swap(u, v); u = to(u, dep[v]); for(int i = M - 1; i >= 0; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i]; return u == v ? u : anc[u][0]; } void work() { int u, v; dep[1] = 0; dfs(1, 1); for(int i = 1; i < M; i++) for(int j = 1; j <= n; j++) anc[j][i] = anc[anc[j][i-1]][i-1]; while(m--) { scanf("%d%d", &u, &v); int f = lca(u, v); int dist = dep[u] + dep[v] - 2 * dep[f]; if(u == v) printf("%d\n", n); else if(dist % 2) printf("0\n"); else if(dep[u] == dep[v]) { int t1 = to(u, dep[u] - dist / 2 + 1); int t2 = to(v, dep[v] - dist / 2 + 1); printf("%d\n", n - size[t1] - size[t2]); } else { if(dep[u] > dep[v]) swap(u, v); int t1 = to(v, dep[v] - dist / 2); int t2 = to(v, dep[v] - dist / 2 + 1); printf("%d\n", size[t1] - size[t2]); } } } int main() { init(); read(); work(); return 0; }