Cod sursa(job #2546582)

Utilizator radustn92Radu Stancu radustn92 Data 14 februarie 2020 11:57:43
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.51 kb
#include <cstdio>
#include <vector>
using namespace std;
const int NMAX = 100505;
const int LMAX = 18;

int N, M, startEuler[NMAX], finishEuler[NMAX], eulerIdx;
int parent[LMAX][NMAX], lg[NMAX];
vector<int> G[NMAX];

void read() {
	scanf("%d%d", &N, &M);
	for (int node = 2; node <= N; node++) {
		scanf("%d", &parent[0][node]);
		G[parent[0][node]].push_back(node);
	}
}

void dfs(int node) {
	startEuler[node] = ++eulerIdx;
	for (auto& neighbour : G[node]) {
		dfs(neighbour);
	}
	finishEuler[node] = ++eulerIdx;
}

void binaryLifting() {
	for (int depth = 2; depth <= N; depth++) {
		lg[depth] = lg[depth >> 1] + 1;
	}

	for (int powIdx = 1; (1 << powIdx) <= N; powIdx++) {
		for (int node = 1; node <= N; node++) {
			parent[powIdx][node] = parent[powIdx - 1][parent[powIdx - 1][node]];
		}
	}
}

inline bool isNode2AncestorOf(int node1, int node2) {
	return startEuler[node1] <= startEuler[node2] && finishEuler[node2] <= finishEuler[node1];
}

int findLca(int node1, int node2) {
	if (isNode2AncestorOf(node1, node2)) {
		return node1;
	}

	for (int depth = lg[N]; depth >= 0; depth--) {
		if (!isNode2AncestorOf(parent[depth][node1], node2)) {
			node1 = parent[depth][node1];
		}
	}
	return parent[0][node1];
}

void solve() {
	dfs(1);
	startEuler[0] = 0; finishEuler[0] = eulerIdx + 1;
	binaryLifting();

	int x, y;
	for (int query = 0; query < M; query++) {
		scanf("%d%d", &x, &y);
		printf("%d\n", findLca(x, y));
	}
}

int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

	read();
	solve();
	return 0;
}