pre文章:树链剖分 - OI Wiki
配套习题:【模板】最近公共祖先(LCA) - 洛谷
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int fa[N], dep[N], siz[N], son[N], top[N];
int head[N], cnt;
struct node {
int v, ne;
}e[N<<1];
void add(int u, int v) {
e[++cnt].v = v, e[cnt].ne = head[u], head[u] = cnt;
}
void dfs1(int now) {
siz[now] = 1;
for (int i = head[now]; i; i = e[i].ne) {
if (dep[e[i].v]) continue;
dep[e[i].v] = dep[now] + 1;
fa[e[i].v] = now;
dfs1(e[i].v);
siz[now] += siz[e[i].v];
if (!son[now] || siz[son[now]] < siz[e[i].v]) son[now] = e[i].v;
}
}
void dfs2(int now, int tp) {
top[now] = tp;
if (son[now]) dfs2(son[now], tp);
for (int i = head[now]; i; i = e[i].ne) {
if (e[i].v == son[now] || e[i].v == fa[now]) continue;
dfs2(e[i].v, e[i].v);
}
}
int lca(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) u = fa[top[u]];
else v = fa[top[v]];
}
return dep[u] < dep[v] ? u : v;
}
int main() {
int n, m, s; cin >> n >> m >> s;
for (int i = 1; i <= n - 1; i++) {
int u, v; cin >> u >> v;
add(u, v); add(v, u);
}
dep[s] = 1;
dfs1(s);
dfs2(s, s);
while (m--) {
int a, b; cin >> a >> b;
cout << lca(a, b) << endl;
}
return 0;
}