倍增找 LCA 其实是一种二进制的思想
先二进制的跳到同一高度,然后再尽可能的一起往上跳。有种 lower_bound - 1 的感觉
#include<bits/stdc++.h>
#define repE(i,u) for(int i = head[u];i;i = E[i].next)
using namespace std;
const int N = 1e6 + 10;
int f[N][32];
int dep[N];
struct Edge {
int to, next;
}E[N << 1];
int head[N], tot;
void addEdge(int from, int to) {
E[++tot] = Edge{ to,head[from] };
head[from] = tot++;
}
void init(int u, int p) {
dep[u] = dep[p] + 1;
f[u][0] = p;
for (int x = 1; (1 << x) < dep[u]; x++) {
f[u][x] = f[f[u][x - 1]][x - 1];
}
repE(i, u) {
if (E[i].to == p)continue;
init(E[i].to, u);
}
}
int LCA(int x, int y) {
if (dep[x] < dep[y])swap(x, y);
while (dep[x] != dep[y]) {
int u = dep[x] - dep[y];
int v = 0;
while (!(u & (1 << v)))v++;
x = f[x][v];
}
while (x != y) {
int v = 0;
while (f[x][v] != f[y][v])v++;
x = f[x][max(0,v - 1)]; y = f[y][max(0,v - 1)];
}
return x;
}
int n, m, root;
int main() {
scanf("%d%d%d", &n, &m, &root);
for (int i = 1; i < n; i++) {
int x, y; scanf("%d%d", &x, &y);
addEdge(x, y);
addEdge(y, x);
}
init(root, 0);
for (int i = 1; i <= m; i++) {
int x, y; scanf("%d%d", &x, &y);
printf("%d
", LCA(x, y));
}
}
顺带复习一波st表
void init() {
for (int i = 1; i <= n; i++) {
f[i][0] = A[i];
}
for (int j = 1; (1 << j) <= n; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
f[i][j] = max(f[i][j - 1], f[i + (1 << (j-1))][j - 1]);
}
}
}
int query(int l, int r) {
int k = log2(r - l + 1);
return max(f[l][k], f[r - (1 << k) + 1][k]);
}