Cod sursa(job #499569)

Utilizator vlad_DVlad Dumitriu vlad_D Data 10 noiembrie 2010 11:06:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.27 kb
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;
vector<vector<int> > G;
int N;
int euler[200010];
int lev[200010];
int RMQ[19][200010];
int poz[100010];
inline void dfs(int nod, int level) {
	euler[++euler[0]] = nod;
	lev[euler[0]] = level;
	poz[nod] = euler[0];
	for (int i = 0; i < G[nod].size(); ++i) {
		dfs(G[nod][i], level+1);
		euler[++euler[0]] = nod;
		lev[euler[0]] = level;
	}
}
int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	int M;
	scanf("%d %d", &N, &M);
	G.resize(N+1);
	for (int i = 2; i <= N; ++i) {
		int tata;
		scanf("%d", &tata);
		G[tata].push_back(i);
	}
	dfs(1, 0);
	// init RMQ
	for (int i = 1; i <= euler[0]; ++i) RMQ[0][i] = i;
	for (int l = 1; l <= 19; ++l) 
		for (int i = 1; i + (1 << l) <= euler[0]; ++i) {
			int end = i + (1 << l) - 1;
			if (lev[RMQ[l-1][i]] < lev[RMQ[l-1][end-((1<<l)>>1) + 1]])
				RMQ[l][i] = RMQ[l-1][i];
			else RMQ[l][i] = RMQ[l-1][end-((1<<l)>>1) + 1];
		}
	while (M--) {
		int a, b;
		scanf("%d %d", &a, &b);
		a = poz[a]; b = poz[b]; if (b < a) swap(a, b);
		int len = b - a + 1;
		int p = 0;
		while ((1 << p) <= len) ++p;
		--p;
		int bst = RMQ[p][a];
		if (p && lev[RMQ[p][b-(1<<p)+1]] < lev[bst]) bst =
			RMQ[p][b-(1<<p)+1];
		printf("%d\n", euler[bst]);
	}
	return 0;
}