Cod sursa(job #423117)

Utilizator Addy.Adrian Draghici Addy. Data 23 martie 2010 15:31:38
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.42 kb
#include <cstdio>
#include <vector>

using namespace std;

#define NMAX 100050
#define LMAX 20

int E[NMAX << 1], L[NMAX << 1], F[NMAX], lg[NMAX << 1];
int rmq[LMAX][NMAX << 1], n, m, k, i, x, y;
vector <int> A[NMAX];

void citire() {
	int i, x;
	
	scanf("%d %d", &n, &m);
	for (i = 2; i <= n; i++) {
		scanf("%d", &x);
		A[x].push_back(i);
	}
}

void DFS(int nod, int lev) {
	int i, fiu;
	
	E[++k] = nod, F[nod] = k, L[k] = lev;
	for (i = 0; i < A[nod].size(); i++) {
		fiu = A[nod][i];
		DFS(fiu, lev + 1);
		E[++k] = nod, L[k] = lev;
	}
}

void RMQ() {
	int i, j;
	
	for (i = 2; i <= k; i++)
		lg[i] = lg[i >> 1] + 1;
	
	for (i = 1; i <= k; i++)
		rmq[0][i] = i;
	
	for (j = 1; (1 << j) <= k; j++)
		for (i = 1; i + (1 << j) - 1 <= k; i++)
			if (L[rmq[j-1][i]] < L[rmq[j - 1][i + (1 << (j - 1))]])
				rmq[j][i] = rmq[j-1][i];
			else
				rmq[j][i] = rmq[j - 1][i + (1 << (j - 1))];
}

int LCA(int x, int y) {
	int t, dif, a = F[x], b = F[y], sol;
	
	if (a > b)
		swap(a, b);
	
	dif = b - a + 1;
	t = lg[dif];
	
	if (L[rmq[t][a]] < L[rmq[t][b - (1 << t) + 1]] )
		sol = rmq[t][a];
	else
		sol = rmq[t][b - (1 << t) + 1];
	
	return E[sol];
}

int main() {
	
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	
	citire();
	
	DFS(1, 1);
	
	RMQ();
	
	for (i = 1; i <= m; i++) {
		scanf("%d %d", &x, &y);
		printf("%d\n", LCA(x, y));
	}
	
	return 0;
}