Cod sursa(job #3274996)

Utilizator amcbnCiobanu Andrei Mihai amcbn Data 8 februarie 2025 17:30:14
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.02 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");

// Data structure that computes LCA in O(1) per query using RMQ
struct LowestCommonAncestor {
	int V = 0;
	LowestCommonAncestor(int V, int root = 1) : V(V) {
		g.resize(V + 1);
	}
	void addEdge(int u, int v) {
		g[u].push_back(v);
		g[v].push_back(u);
	}
	void build() {
		pos.resize(V + 1);
		depth.resize(V + 1);
		function<void(int, int)> dfs = [&](int u, int par) {
			pos[u] = tour.size();
			tour.push_back(u);
			for (auto& v : g[u]) {
				if (v == par) {
					continue;
				}
				depth[v] = depth[u] + 1;
				dfs(v, u);
				tour.push_back(u);
			}
		};
		dfs(1, -1);
		len = tour.size();
		t.resize(4 * len + 1);
		build(1, 0, len - 1);
	}
	int lca(int u, int v) {
		int l = pos[u], r = pos[v];
		if (l > r) {
			swap(l, r);
		}
		return query(1, 0, len - 1, l, r);
	}
private:
	vector<int> depth, pos;
	vector<vector<int>> g;
	int len;
	vector<int> tour, t;
	int compare(int u, int v) {
		return depth[u] < depth[v] ? u : v;
	}
	void build(int node, int l, int r) {
		if (l == r) {
			t[node] = tour[l];
			return;
		}
		int mid = (l + r) / 2;
		build(node << 1, l, mid);
		build(node << 1 | 1, mid + 1, r);
		t[node] = compare(t[node << 1], t[node << 1 | 1]);
	}
	int query(int node, int l, int r, int ql, int qr) {
		if (ql <= l && r <= qr) {
			return t[node];
		}
		int mid = (l + r) / 2;
		if (ql <= mid) {
			if (mid < qr) {
				return compare(query(node << 1, l, mid, ql, qr), query(node << 1 | 1, mid + 1, r, ql, qr));
			}
			else {
				return query(node << 1, l, mid, ql, qr);
			}
		}
		else {
			return query(node << 1 | 1, mid + 1, r, ql, qr);
		}
	}
};

int n, q;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
	cin >> n >> q;
	LowestCommonAncestor foo(n);
	for (int i = 2; i <= n; ++i) {
		int par;
		cin >> par;
		foo.addEdge(par, i);
	}
	foo.build();
	while (q--) {
		int u, v;
		cin >> u >> v;
		cout << foo.lca(u, v) << "\n";
	}
}