Cod sursa(job #935274)

Utilizator sleepaholicNeculaescu Theodor sleepaholic Data 2 aprilie 2013 17:12:13
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.57 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

const int MAX_N = 100005;
const int MAX_logN = 20;

int n, m, Log[MAX_N << 1], euler[MAX_N << 1], nivel[MAX_N << 1], poz[MAX_N], cnt;
int rmq[MAX_N << 2][MAX_logN];

bool used[MAX_N];
vector <int> L[MAX_N];

void read() {
	f >> n >> m;
	for (int i = 2; i <= n; i++) {
		int x;
		f >> x;
		L[x].push_back(i);
	}
}

void dfs(int nod, int level) {
	euler[++cnt] = nod;
	nivel[cnt] = level;
	poz[nod] = cnt;

	for (int i = 0; i < L[nod].size(); i++) {
		int vecin = L[nod][i];
		if (!used[vecin]) {
			dfs(vecin, level + 1);
			euler[++cnt] = nod;
			nivel[cnt] = level;
		}
	}
}

void precompute_rmq() {
	Log[1] = 0;

	for (int i = 2; i <= cnt; i++)
		Log[i] = Log[i / 2] + 1;

	for (int i = 1; i <= cnt; i++)
		rmq[i][0] = i;

	for (int j = 1; (1 << j) < cnt; j++)
		for (int i = 1; i + (1 << (j - 1)) <= cnt; i++)
			if (nivel[rmq[i][j - 1]] <= nivel[rmq[i + (1 << (j - 1))][j - 1]])
				rmq[i][j] = rmq[i][j - 1];
			else
				rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1];
}

void solve() {
	while (m--) {
		int i, j, ind;

		f >> i >> j;
		i = poz[i];	j = poz[j];
		if (i > j)
			swap(i, j);

		int k = Log[j - i + 1];

		if (nivel[rmq[i][k]] <= nivel[rmq[j - (1 << k) + 1][k]])
			ind = rmq[i][k];
		else
			ind = rmq[j - (1 << k) + 1][k];

		g << euler[ind] << '\n';
	}
}

int main() {
	read();
	dfs(1, 1);		// aflu parcurgerea euler si nivelurile
	precompute_rmq();
	solve();

	f.close();
	g.close();

	return 0;
}