Cod sursa(job #1599495)

Utilizator andrei_diaconuAndrei Diaconu andrei_diaconu Data 13 februarie 2016 21:59:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.65 kb
#include <fstream>
#include <vector>

#define NMax 100010

using namespace std;

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

int nodes, queries, RMQ[18][2 * NMax], lg[2 * NMax], euler[2 * NMax], firstOc[NMax], k, level[2 * NMax];
bool mark[NMax];
vector<int> G[NMax];

int getMin(int a, int b)
{
	if (a < b)
		return a;
	return b;
}

int getMax(int a, int b)
{
	if (a > b)
		return a;
	return b;
}

void DFS(int node, int lvl)
{
	mark[node] = true;
	euler[++k] = node;
	level[k] = lvl;

	for (vector<int>::iterator it = G[node].begin(); it != G[node].end(); it++) {
		mark[*it] = true;
		DFS(*it, lvl + 1);
		euler[++k] = node;
		level[k] = lvl;
	}
}

int main()
{
	for (int i = 2; i <= 2 * NMax - 1; i++)
		lg[i] = lg[i / 2] + 1;

	f >> nodes >> queries;

	int node;
	for (int i = 2; i <= nodes; i++) {
		f >> node;
		G[node].push_back(i);
	}

	DFS(1, 0);

	for (int i = 1; i <= k; i++) {
		if (!firstOc[euler[i]])
			firstOc[euler[i]] = i;

		RMQ[0][i] = i;
	}

	for (int i = 1; i <= lg[k]; i++) {
		for (int j = 1; j <= k - (1 << i) + 1; j++) {
			if (level[RMQ[i - 1][j]] < level[RMQ[i - 1][j + (1 << (i - 1))]])
				RMQ[i][j] = RMQ[i - 1][j];
			else
				RMQ[i][j] = RMQ[i - 1][j + (1 << (i-1))];
		}
	}

	int n1, n2;
	for (int i = 1; i <= queries; i++) {
		f >> n1 >> n2;
		int pos1 = getMin(firstOc[n1], firstOc[n2]);
		int pos2 = getMax(firstOc[n1], firstOc[n2]);

		int span = lg[pos2 - pos1 + 1];

		if (level[RMQ[span][pos1]] < level[RMQ[span][pos2 - (1 << span) + 1]])
			g << euler[RMQ[span][pos1]] << "\n";
		else
			g << euler[RMQ[span][pos2 - (1 << span) + 1]] << "\n";
	}

	return 0;
}