Cod sursa(job #1918470)

Utilizator andrei_diaconuAndrei Diaconu andrei_diaconu Data 9 martie 2017 15:31:27
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 1.68 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define NMax 100010
#define LogMax 17

using namespace std;

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

int nodes, euler[2 * NMax], level[2 * NMax], RMQ[LogMax][2*NMax], lg2[2*NMax], queries, firstOcc[NMax];
bool mark[NMax];
vector<int> G[NMax];

void DFS(int node, int lvl)
{
	mark[node] = true;

	++euler[0];
	euler[euler[0]] = node;
	level[euler[0]] = lvl;

	for (auto it : G[node]) {
		if (!mark[it]) {
			DFS(it, lvl + 1);
			++euler[0];
			euler[euler[0]] = node;
			level[euler[0]] = lvl;
		}
	}
}

void PreCompRMQ()
{
	for (int i = 1; i <= euler[0]; i++) {
		RMQ[0][i] = i;
		if (firstOcc[euler[i]] == 0)
			firstOcc[euler[i]] = i;
	}

	for (int i = 1; i <= lg2[euler[0]]; i++)
		for (int j = 1; j <= euler[0] - (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 query_range(int left, int right)
{
	int span = lg2[right - left + 1];

	if (level[RMQ[span][left]] < level[RMQ[span][right - (1 << span) + 1]])
		return RMQ[span][left];
	return RMQ[span][right - (1 << span) + 1];
}

int main()
{
	f >> nodes >> queries;
	for (int i = 2; i <= 2 * nodes; i++)
		lg2[i] = lg2[i / 2] + 1;

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

	DFS(1, 0);
	PreCompRMQ();

	for (int i = 1; i <= queries; i++) {
		f >> n1 >> n2;

		int left = firstOcc[n1];
		int right = firstOcc[n2];
		if (left > right)
			swap(left, right);

		int idx = query_range(left, right);
		g << euler[idx] << '\n';
	}
	return 0;
}