LCA线段树求调!!
查看原帖
LCA线段树求调!!
519573
Daniel_yao楼主2022/7/24 15:29
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int N = 500005;

int n, m, s, top, top1, tree[4 * N], id[N], idf[N]; 

int ans[N]; //LCA (编号)
int idx[N]; //LCA (序号)
int cnt; //序号  

vector <int> e[N];

void dfs(int x, int fa){
	ans[++top] = x;
	if(id[x] == -1) id[x] = ++cnt;
	for (int i = 0; i < e[x].size(); i++) {
		int y = e[x][i];
		if(y != fa){
			dfs(y, x);
		}
		ans[++top] = x;
	}
} 

void build(int node, int start, int end){
	if(start == end){
//		cout << 1 << '\n';
		tree[node] = idx[start];
		return ;
	}
	int mid = (start + end) / 2;
	int l = node * 2;
	int r = node * 2 + 1;
	build(l, start, mid);
	build(r, mid + 1, end);
	tree[node] = min(tree[l], tree[r]);
}

int query(int node, int start, int end, int L, int R){
	if(L <= start && end <= R){
		return tree[node];
	}
	int mid = (start + end) / 2, ans = 0x3f;
	int l = node * 2;
	int r = node * 2 + 1;
	if(mid >= L){
		ans = min(ans, query(l, start, mid, L, R));
	}
	if(mid < R){
		ans = min(ans, query(r, mid + 1, end, L, R));
	}
	return ans;
}

int main() {
	memset(tree, 0x3f, sizeof tree);
	memset(id, -1, sizeof id);
	memset(idf, -1, sizeof idf);
	cin >> n >> m >> s;
	for (int i = 1; i < n; i++) {
		int u, v; cin >> u >> v;
		e[v].push_back(u);
	}
	dfs(s, -1);
	for (int i = 1; i <= top; i++) {
		idx[i] = id[ans[i]];//LCA (序号)
	}
	for (int i = 1; i <= top; i++) {
		if(idf[idx[i]] == -1) idf[idx[i]] = i;
	}
	/* idf : n, idx : top*/
//	for(int i = 1;i <= top;i++){
//		cout << ans[i] << ' ';
//	}
	build(1, 1, top);
	while(m--) {
		int x, y, k;
		cin >> x >> y;
		if(idf[id[x]] > idf[id[y]]){
			k = query(1, 1, top, idf[id[y]], idf[id[x]]);
		} else {
			k = query(1, 1, top, idf[id[x]], idf[id[y]]); 
		} 
		cout << ans[id[k]] << '\n';
	}
} 

/*
10 10 8
10 9
3 1
8 2
3 8
7 3
5 9
8 5
8 6
4 6
8 4
6 1
7 1
10 1
6 1
9 1
4 1
7 1
10 1
10 1

*/
 
2022/7/24 15:29
加载中...