Cod sursa(job #556158)

Utilizator cnt_tstcont teste cnt_tst Data 15 martie 2011 23:22:49
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 1.5 kb
#include <cstdio>
#include <list>

using namespace std;

#define NMAX 100050
#define LMAX 20

int E[NMAX << 1], L[NMAX << 1], F[NMAX], rmq[LMAX][NMAX], log[NMAX << 1], n, m, k, i, x, y;
list <int> G[NMAX];

int LCA (int, int);
void citire (), RMQ (), DFS (int, int);

int main () {
	
	citire ();
	
	DFS (1, 0);
	
	RMQ ();
	
	for (i = 1; i <= m; i++) {
		scanf ("%d %d", &x, &y);
		printf ("%d\n", LCA (x, y));
	}
	
	return 0;
}

void citire () {
	
	freopen ("lca.in", "r", stdin);
	freopen ("lca.out", "w", stdout);
	
	int i, x;
	
	scanf ("%d %d", &n, &m);
	
	for (i = 2; i <= n; i++) {
		scanf ("%d", &x);
		G[x].push_back (i);
	}
}

void DFS (int nod, int lev) {
	
	list <int>::iterator it;
	
	E[++k] = nod, L[k] = lev, F[nod] = k;
	for (it = G[nod].begin (); it != G[nod].end (); it++) {
		if (!F[*it]) DFS (*it, lev + 1);
		E[++k] = nod, L[k] = lev;
	}
}

void RMQ () {
	
	int i, j;
	
	for (i = 2; i <= k; i++) log[i] = log[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 sol, t, a = F[x], b = F[y];
	
	if (a > b) swap (a, b);
	
	t = log[b - a + 1];
	
	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];
}