Cod sursa(job #517346)

Utilizator alex_mircescuAlex Mircescu alex_mircescu Data 28 decembrie 2010 15:24:55
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.43 kb
#include <stdio.h>
#include <vector>

#define MAXN 100010*2

using namespace std;

long n, m, i, val, v[3][MAXN], co, rMq[20][MAXN], put, j, st, en, p, first[MAXN], last[MAXN];
vector <long> a[MAXN];

void BuildA(long nod, long nivel) {
	v[1][++co] = nod;
	v[2][co] = nivel;
	if (first[nod] == 0) first[nod] = co;
	last[nod] = co;
	long aux = a[nod].size();
	for (long i = 0; i < aux; ++i) {
		BuildA(a[nod][i], nivel + 1);
		v[1][++co] = nod;
		v[2][co] = nivel;			
	}
}

int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	scanf("%ld %ld", &n, &m);

	for (i = 1; i < n; ++i) {
		scanf("%ld", &val);
		a[val].push_back(i + 1);
	}
	
	BuildA(1, 0);
	
	n = co;
	for (i = 1; i <= n; ++i) 
		rMq[1][i] = i;
	
	for (i = 2, put = 2; put <= n; ++i, put <<= 1) {
		for (j = 1; j <= n; ++j) {
			rMq[i][ j ] = rMq[i - 1][j];
			if (j + (put / 2) <= n)
			if (v[1][rMq[i - 1][j + (put / 2)]] < v[1][rMq[i - 1][j]]) {
				rMq[i][j] = rMq[i - 1][j + (put /2 )];
			}
		}
	}
	
	for (i = 1; i <= m; ++i) {
		scanf("%ld %ld", &st, &en);
		st = first[st];
		en = last[en];
		if( st > en)
			en = st ^ en ^ ( st = en );
		p = 1; 
		val = 0;
		while (p * 2 <= (en - st + 1)) {p *= 2;++val;}
		if (v[1][rMq[val + 1][st]] < v[1][rMq[val + 1][en - p + 1]]) {
			printf("%ld\n", v[1][rMq[val + 1][st]]);
		} else {
			printf("%ld\n", v[1][rMq[val + 1][en - p + 1]]);			
		}
	}
	
	return 0;
}