Cod sursa(job #2719481)

Utilizator ardutgamerAndrei Bancila ardutgamer Data 9 martie 2021 21:40:55
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.69 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

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

const int NMAX = 100005;
const int LOGMAX = 20;
const int INF = 2e9;

vector<int>G[NMAX];
int posMin[NMAX];
int posMax[NMAX];
int lg2[3*NMAX];
int rmq[3*NMAX][LOGMAX];

int m, n, e;

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

vector<int>euler;

void dfs(int u,int parent = -1)
{
	for (int v : G[u])
	{
		if (v != parent)
		{
			euler.push_back(v);
			dfs(v, u);
			euler.push_back(u);
		}
	}
}

void precalc()
{
	euler.push_back(-1);
	for (int i = 1; i <= n; i++)
	{
		posMin[i] = INF;
		posMax[i] = 0;
	}
	euler.push_back(1);
	dfs(1);
	e = euler.size() - 1;
	for (int i = 1; i <= e ; i++)
	{
		posMin[euler[i]] = min(posMin[euler[i]], i);
		posMax[euler[i]] = max(posMax[euler[i]], i);
	}

	lg2[1] = 0;
	for (int i = 2; i <= e; i++)
		lg2[i] = lg2[(i / 2)] + 1;

	for (int i = 1; i <= e; i++) {
		//fout << euler[i] << ' ';
		rmq[i][0] = euler[i];
	}
	//fout << '\n';
	for (int j = 1; (1 << j) <= e; j++)
		for (int i = 1; i + (1 << j) -1 <= e; i++)
			rmq[i][j] = min(rmq[i+(1<<(j-1))][j - 1], rmq[i][j-1]);
}

int RMQuery(int a, int b)
{
	int l = b - a + 1;
	int lg = lg2[l];
	return min(rmq[a][lg], rmq[b - (1 << lg) + 1][lg]);
}

int lca(int a, int b)
{
	//fout << posMin[a] << ' ' << posMax[b] << '\n';
	return RMQuery(posMin[a], posMax[b]);
}

void solve()
{
	while (m--)
	{
		int a, b;
		fin >> a >> b;
		fout << lca(a, b) << '\n';
	}
}

int main()
{
	read();
	precalc();
	solve();
	return 0;
}