Cod sursa(job #2806590)

Utilizator lucamLuca Mazilescu lucam Data 22 noiembrie 2021 20:17:29
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.01 kb
#include <bits/stdc++.h>

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

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

template<typename T>
using func = std::function<T>;

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

int n, m;
std::vector<int> g[N];
int euler[2 * N];
int euler_count;
int levels[N];
int sparse_table[LOG2N][N];
int euler_indices[N];

void read() {
	in >> n >> m;
	for (int i = 1; i <= n - 1; ++i) {
		int u, v;
		in >> u;
		v = i + 1;
		g[u].push_back(v);
		g[v].push_back(u);
	}
}

void build_levels() {
	func<void(int, int)> dfs = [&](int u, int level) {
		levels[u] = level;
		for (auto v : g[u]) {
			if (levels[v] == 0) {
				dfs(v, level + 1);
			}
		}
	};
	dfs(1, 1);
}

void build_euler() {
	func<void(int, int)> dfs = [&](int u, int parent) {
		euler[++euler_count] = u;
		euler_indices[u] = euler_count;
		for (auto v : g[u]) {
			if (v != parent) {
				dfs(v, u);
				euler[++euler_count] = u;
			}
		}
	};
	dfs(1, 1);
}

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

void build_sparse_table() {
	for (int i = 1; i <= euler_count; ++i) {
		sparse_table[0][i] = euler[i];
	}
	for (int exp2 = 1; exp2 < LOG2N; ++exp2) {
		int p2 = 1 << exp2;
		for (int i = 1; i + p2 <= euler_count; ++i) {
			sparse_table[exp2][i] = min_level_node(sparse_table[exp2 - 1][i], sparse_table[exp2 - 1][i + p2 / 2]);
		}
	}
}

int floor_log2(int x) {
	return 32 - __builtin_clz(x) - 1;
}

int query_sparse_table(int l, int r) {
	int len_exp = floor_log2(r - l + 1);
	int len = 1 << len_exp;
	return min_level_node(sparse_table[len_exp][l], sparse_table[len_exp][r - len + 1]);
}

int lca(int u, int v) {
	int l = euler_indices[u], r = euler_indices[v];
	if (l > r) {
		std::swap(l, r);
	}
	return query_sparse_table(l, r);
}

int main() {
	read();
	build_levels();
	build_euler();
	build_sparse_table();
	for (int i = 1; i <= m; ++i) {
		int u, v;
		in >> u >> v;
		out << lca(u, v) << "\n";
	}
}