Cod sursa(job #403005)

Utilizator katakunaCazacu Alexandru katakuna Data 24 februarie 2010 14:25:27
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 1.33 kb
#include <cstdio>
#include <vector>
using namespace std;

#define Nmax 100010

int n, T, N, niv, k;
int E[Nmax << 1], Niv[Nmax << 1], poz[Nmax << 1], lg[Nmax << 1], rmq[18][Nmax << 1];
vector <int> V[Nmax];

void euler (int nod) {
	
	E[++N] = nod; Niv[N] = niv; poz[nod] = N;
	for (int i = 0; i < (int)V[nod].size (); i++) {
		niv++;
		euler (V[nod][i]);
		niv--; E[++N] = nod; Niv[N] = niv;
	}
}

void Rmq () {
	
	int i, l1, l2; rmq[0][1] = 1;
	for (i = 2; i <= N; i++)
		rmq[0][i] = i, lg[i] = lg[i >> 1] + 1;
	
	for (k = 1; (1 << k) <= N; k++)  {
		l1 = (1 << k); l2 = (1 << (k - 1));
		for (i = 1; i + l1 - 1 <= N; i++) 
			if ( Niv[ rmq[k-1][i + l2] ] < Niv[ rmq[k-1][i] ] )
				rmq[k][i] = rmq[k-1][i + l2];
			else
				rmq[k][i] = rmq[k-1][i];
	}
}

int main () {

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

	scanf ("%d %d", &n, &T);
	int x;
	for (int i = 2; i <= n; i++) 
		scanf ("%d", &x), V[x].push_back (i);
	
	niv++; euler (1);
	
	Rmq ();
	
	int a, b, y, k;
	for (; T; T--) {
		scanf ("%d %d", &x, &y);
		if (poz[x] < poz[y]) 
			a = poz[x], b = poz[y];
		else
			a = poz[y], b = poz[x];
		
		k = lg[b - a + 1];
		a = rmq[k][a]; b = rmq[k][b - (1 << k) + 1] ;
		if (Niv[a] < Niv[b])
			printf ("%d\n", E[a]);
		else
			printf ("%d\n", E[b]);
	}
	
	return 0;
}