LCA倍增

倍增找 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]);
}
原文地址:https://www.cnblogs.com/sduwh/p/13811705.html