【图论】树上最近公共祖先
int dis[200005];
int fa[200005][20];
void dfslca(int u, int p) {
dis[u] = dis[p] + 1;
fa[u][0] = p;
for(int i = 1; i < 20; ++i)
fa[u][i] = fa[fa[u][i - 1]][i - 1];
for(int v : G[u]) {
if(v == p)
continue;
dfslca(v, u);
}
}
int lift(int x, int D) {
for(int i = 20 - 1; i >= 0; --i) {
if(dis[fa[x][i]] >= D)
x = fa[x][i];
}
return x;
}
int lca(int x, int y) {
if(dis[x] < dis[y])
swap(x, y);
for(int i = 20 - 1; i >= 0; --i) {
if(dis[fa[x][i]] >= dis[y])
x = fa[x][i];
}
if(x == y)
return x;
for(int i = 20 - 1; i >= 0; --i) {
if(fa[x][i] != fa[y][i]) {
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
重链剖分
struct TreeChain {
static const int MAXN = 100000 + 10;
struct Edge {
struct EdgeNode {
int v, nxt;
} en[MAXN << 1];
int h[MAXN], top;
void Init(int n) {
top = 0;
memset(h, 0, sizeof(h[0]) * (n + 1));
}
void Add(int u, int v) {
en[++top] = {v, h[u]}, h[u] = top;
en[++top] = {u, h[v]}, h[v] = top;
}
} edge;
int dep[MAXN], siz[MAXN], mch[MAXN], pat[MAXN];
int top[MAXN], tid[MAXN], cnt;
void Init(int r) {
edge.Init(n);
for(int i = 1, u, v; i <= n - 1; ++i) {
scanf("%d%d", &u, &v);
edge.Add(u, v);
}
cnt = 0;
dfs1(r, 0);
dfs2(r, r);
}
void dfs1(int u, int p) {
dep[u] = dep[p] + 1, siz[u] = 1, mch[u] = 0, pat[u] = p;
for(int i = edge.h[u]; i; i = edge.en[i].nxt) {
int v = edge.en[i].v;
if(v == p)
continue;
dfs1(v, u);
siz[u] += siz[v];
if(mch[u] == 0 || siz[v] > siz[mch[u]])
mch[u] = v;
}
}
void dfs2(int u, int t) {
top[u] = t, tid[u] = ++cnt;
if(mch[u] != 0)
dfs2(mch[u], t);
for(int i = edge.h[u]; i; i = edge.en[i].nxt) {
int v = edge.en[i].v;
if(v == pat[u] || v == mch[u])
continue;
dfs2(v, v);
}
}
int lca(int u, int v) {
for(int tu = top[u], tv = top[v]; tu != tv; u = pat[tu], tu = top[u]) {
if(dep[tu] < dep[tv])
swap(u, v), swap(tu, tv);
}
return (dep[u] <= dep[v]) ? u : v;
}