Cod sursa(job #2651059)

Utilizator sebimihMihalache Sebastian sebimih Data 21 septembrie 2020 15:44:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.44 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

const int N = 1e5 + 5, MAXLOG = 18;

vector<int> g[N];
int rmq[2 * N][MAXLOG], SirEuler[2 * N], lvl[N], pos[N], Log2[2 * N];

void df(int nod, int nivel)
{
	lvl[nod] = nivel;
	SirEuler[++SirEuler[0]] = nod;
	pos[nod] = SirEuler[0];
	for (int neigh : g[nod])
	{
		df(neigh, nivel + 1);
		SirEuler[++SirEuler[0]] = nod;
	}
}

int GetMin(int x, int y)
{
	if (lvl[x] < lvl[y])
	{
		return x;
	}
	return y;
}

void precompute()
{
	// Sirul Euler
	df(1, 0);

	Log2[1] = 0;
	for (int i = 2; i <= SirEuler[0]; i++)
	{
		Log2[i] = Log2[i / 2] + 1;
	}

	for (int i = 1; i <= SirEuler[0]; i++)
	{
		rmq[i][0] = SirEuler[i];
	}

	for (int p = 1; (1 << p) <= SirEuler[0]; p++)
	{
		for (int i = 1; i + (1 << p) <= SirEuler[0]; i++)
		{
			rmq[i][p] = GetMin(rmq[i][p - 1], rmq[i + (1 << (p - 1))][p - 1]);
		}
	}
}

int SolveQuery(int x, int y)
{
	int px = pos[x];
	int py = pos[y];
	
	if (px > py)
	{
		swap(px, py);
	}

	int dif = py - px + 1;
	int level = Log2[dif];
	return GetMin(rmq[px][level], rmq[py - (1 << level) + 1][level]);
}

int main()
{
	int n, m;
	fin >> n >> m;

	for (int i = 2; i <= n; i++)
	{
		int t;
		fin >> t;
		g[t].push_back(i);
	}

	precompute();

	while (m--)
	{
		int x, y;
		fin >> x >> y;
		fout << SolveQuery(x, y) << '\n';
	}
}