Cod sursa(job #2803464)

Utilizator lucamLuca Mazilescu lucam Data 20 noiembrie 2021 01:09:06
Problema Lowest Common Ancestor Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.42 kb
#include <bits/stdc++.h>

std::ifstream in("lca.in");
std::ofstream out("lca.out");

constexpr int N = 1e5, M = 2e6, LOG_N = 13;

int n;
std::vector<int> g[N];
std::pair<int, int> pairs[M];
int ancest[LOG_N + 1][N];
int depth[N];

void find_levels() {
	std::function<void(int, int)> dfs = [&](int u, int level) {
		depth[u] = level;
		for (int v : g[u]) {
			if (depth[v] == 0) {
				dfs(v, level + 1);
			}
		}
	};
	dfs(0, 1);
}

void build_ancest() {
	std::function<void(int, int)> dfs = [&](int u, int above) {
		ancest[0][u] = above;
		for (int exp = 1; exp <= LOG_N; ++exp) {
			ancest[exp][u] = ancest[exp - 1][ancest[exp - 1][u]];
		}
		for (int v : g[u]) {
			if (v != above) {
				dfs(v, u);
			}
		}
	};
	dfs(0, 0);
}

void raise(int &u, int levels) {
	for (int exp = 0; exp <= LOG_N; ++exp) {
		if (levels & (1 << exp)) {
			u = ancest[exp][u];
		}
	}
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) {
		std::swap(u, v);
	}
	raise(u, depth[u] - depth[v]);
	if (u == v) {
		return u;
	}
	for (int exp = LOG_N; exp >= 0; --exp) {
		if (ancest[exp][u] != ancest[exp][v]) {
			u = ancest[exp][u];
			v = ancest[exp][v];
		}
	}
	return ancest[0][u];
}

int main() {
	int m;
	in >> n >> m;
	for (int i = 0; i < n - 1; ++i) {
		int u;
		in >> u;
		--u;
		g[u].push_back(i + 1);
		g[i + 1].push_back(u);
	}
	find_levels();
	build_ancest();
	for (int i = 0; i < m; ++i) {
		int u, v;
		in >> u >> v;
		--u;
		--v;
		out << lca(u, v) + 1 << "\n";
	}
}