Cod sursa(job #1977473)

Utilizator retrogradLucian Bicsi retrograd Data 5 mai 2017 12:03:14
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.55 kb
#include <bits/stdc++.h>

using namespace std;

struct HeavyLight {
	vector<vector<int>> G;
	vector<int> Jump, SubSize, Depth, Lin, Parent;
	bool processed;

	HeavyLight(int n) : 
		G(n), Jump(n), SubSize(n), Depth(n), Lin(n), Parent(n) {}

	void AddEdge(int a, int b) {
		G[a].push_back(b);
		G[b].push_back(a);
	}

	void Preprocess() {
		DFSSub(0, -1);
		DFSJump(0, 0);
		processed = true;
	}

	int GetLCA(int a, int b) {
		assert(processed);

		while (Jump[a] != Jump[b]) {
			if (Depth[Jump[a]] > Depth[Jump[b]])
				a = Parent[Jump[a]];
			else 
				b = Parent[Jump[b]];
		}

		return Depth[a] > Depth[b] ? b : a;
	}

private:
	
	int DFSSub(int node, int par) {
		SubSize[node] = 1;
		Parent[node] = par;
		if (par != -1) {
			G[node].erase(find(G[node].begin(), G[node].end(), par));
			Depth[node] = 1 + Depth[par];
		}

		for (auto vec : G[node])
			SubSize[node] += DFSSub(vec, node);
	
		return SubSize[node];
	}

	int timer = 0;
	int DFSJump(int node, int jump) {
		Jump[node] = jump;
		Lin[node] = timer++;

		sort(G[node].begin(), G[node].end(), [&](int a, int b) {
			return SubSize[a] < SubSize[b];
		});

		for (auto vec : G[node])
			DFSJump(vec, vec == G[node].back() ? jump : vec);
	}
};

int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n, m;
	cin >> n >> m;
	HeavyLight hl(n);

	for (int i = 1; i < n; ++i) {
		int p;
		cin >> p;
		hl.AddEdge(p - 1, i);
	}

	hl.Preprocess();
	while (m--) {
		int a, b;
		cin >> a >> b;
		cout << 1 + hl.GetLCA(a - 1, b - 1) << '\n';
	}
	return 0;
}