Cod sursa(job #2806898)

Utilizator lucamLuca Mazilescu lucam Data 23 noiembrie 2021 10:07:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.46 kb
#include <bits/stdc++.h>

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

template<typename It>
void iter_dbg(It begin, It end) {
	for (auto it = begin; it != end; ++it) {
		std::clog << *it << " ";
	}
	std::clog << "\n";
}

template<typename It, typename F>
void iter_dbg_f(It begin, It end, F &&f) {
	for (auto it = begin; it != end; ++it) {
		std::clog << f(*it, it - begin) << " ";
	}
	std::clog << "\n";
}

constexpr int N = 1e5 + 1, LOG_2N = 17 + 1;

int n;
std::vector<int> g[N];
int st[LOG_2N][2 * N];
int h[N];
int ep[N];

inline int min_level_node(int u, int v) {
	return h[u] < h[v] ? u : v;
}

inline int log2(int x) {
	return std::max(0, 31 - __builtin_clz(x));
}

void prepare() {
	std::function<void(int)> dfs = [&](int u) {
		static int ei;
		st[0][++ei] = u;
		ep[u] = ei;
		for (auto v : g[u]) {
			h[v] = h[u] + 1;
			dfs(v);
			st[0][++ei] = u;
		}
	};
	dfs(1);
	int lim = log2(2 * n); 
	for (int exp = 1; exp <= lim; ++exp) {
		int p = 1 << exp;
		for (int i = 1; i + p <= 2 * n; ++i) {
			st[exp][i] = min_level_node(st[exp - 1][i], st[exp - 1][i + p / 2]);
		}
	}
}

inline int lca(int u, int v) {
	int l = ep[u], r = ep[v];
	if (l > r) {
		std::swap(l, r);
	}
	int k = log2(r - l + 1);
	return min_level_node(st[k][l], st[k][r - (1 << k) + 1]);
}

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