首页 > 代码库 > Hihocoder 最近公用祖先三 在线LCA

Hihocoder 最近公用祖先三 在线LCA

在线的LCA算法,dfs遍历整棵树,对于每个点出现的时候都插入到数组中,然后查询两个点的lca就是两个点在数组中最后出现位置间的dep值最小的点,就转化为链上的RMQ问题了。

#include <cstdio>#include <cstring>#include <algorithm>#include <map>#include <set>#include <bitset>#include <queue>#include <stack>#include <string>#include <iostream>#include <cmath>#include <climits>using namespace std;const int maxn = 1e5 + 10;int head[maxn], nxt[maxn << 1], v[maxn << 1];int rpos[maxn], n, Q, cnt, ecnt;map<string, int> mp;map<int, string> smp;char name1[1024], name2[1024];struct Node {	int dep, id;	bool operator < (const Node &x) const {		return dep < x.dep;	}};Node val[maxn << 1], minv[maxn << 1][30];void adde(int uu, int vv) {	v[ecnt] = vv; nxt[ecnt] = head[uu]; head[uu] = ecnt++;}int getid(char *str) {	if(mp.count(str) == 0) {		int mpz = mp.size();		mp[str] = mpz + 1;		smp[mpz + 1] = str;		return mpz + 1;	}	return mp[str];}void dfs(int now, int fa, int dep) {	val[++cnt].dep = dep; val[cnt].id = now;	for(int i = head[now]; ~i; i = nxt[i]) if(v[i] != fa) {		dfs(v[i], now, dep + 1);		val[++cnt].dep = dep; val[cnt].id = now;	}	rpos[now] = cnt;}void initRMQ() {	for(int i = 1; i <= cnt; i++) {		minv[i][0] = val[i];	}	for(int j = 1; (1 << j) <= cnt; j++) {		for(int i = 1; i + (1 << j) - 1 <= cnt; i++) {			minv[i][j] = min(minv[i][j - 1], minv[i + (1 << (j - 1))][j - 1]);		}	}}Node query(int l, int r) {	int k = 0;	while((1 << (k + 1)) <= r - l + 1) k++;	return min(minv[l][k], minv[r - (1 << k) + 1][k]);}int main() {	memset(head, -1, sizeof(head));	scanf("%d", &n);	for(int i = 1; i <= n; i++) {		scanf("%s%s", name1, name2);		int a = getid(name1), b = getid(name2);		adde(a, b); adde(b, a);	}	dfs(1, -1, 0);	initRMQ();	scanf("%d", &Q);	while(Q--) {		scanf("%s%s", name1, name2);		int a = getid(name1), b = getid(name2);		a = rpos[a]; b = rpos[b];		if(a > b) swap(a, b);		Node ret = query(a, b);		puts(smp[ret.id].c_str());	}	return 0;}

  

Hihocoder 最近公用祖先三 在线LCA