树链剖分

参考链接:https://www.cnblogs.com/dx123/p/16320467.html(感谢董晓老师)

树链剖分求LCA

比倍增快一些
https://www.luogu.com.cn/problem/P3379

#include<bits/stdc++.h>
const int N = 5e5 + 5;
using namespace std;
int n,m,root; 
int h[N],ne[2 * N],e[2 * N],idx;
int dep[N],size[N],son[N],top[N],fa[N];
void add(int a,int b){
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}
void dfs1(int u){
	size[u] = 1;
	dep[u] = dep[fa[u]] + 1;
	for(int i = h[u];~i;i = ne[i]){
		int v = e[i];
		if(v == fa[u]) continue;
		fa[v] = u;
		dfs1(v);
		size[u] += size[v];
		if(!son[u] || size[son[u]] < size[v]) son[u] = v; 
	} 
}
void dfs2(int u,int ttop){
	top[u] = ttop;
	if(son[u]) dfs2(son[u],ttop);
	for(int i = h[u];~i;i = ne[i]){
		int v = e[i];
		if(v == fa[u] || v == son[u]) continue;
		dfs2(v,v);
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> n >> m >> root;
	memset(h,-1,sizeof(h));
	for(int i = 1;i <= n - 1;++i){
		int a,b; cin >> a >> b;
		add(a,b);add(b,a);
	} 
	dfs1(root);
	dfs2(root,root);
	for(int i = 1;i <= m;++i){
		int u,v; cin >> u >> v;
		while(top[u] != top[v]){
			if(dep[top[u]] >= dep[top[v]]) u = fa[top[u]];
			else                           v = fa[top[v]];
		} 
		if(dep[u] < dep[v]) cout << u << '\n';
		else                cout << v << '\n';
	}
	return 0;
} 
posted @ 2024-04-24 21:38  gebeng  阅读(17)  评论(0)    收藏  举报