Cod sursa(job #2354658)

Utilizator Radu_FilipescuFilipescu Radu Radu_Filipescu Data 25 februarie 2019 14:36:30
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.47 kb
#include <vector>
#include <fstream>

using namespace std;

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

const int MAXN = 100005;
const int MAXK = 20;

int N, M;
int euler[MAXN * 2], h[MAXN * 2], lg[MAXN * 2], pos[MAXN], last;
int rmq[MAXK][MAXN];

vector <int> Ad[MAXN];

void citire()
{
	fin >> N >> M;

	int x;

	for( int i = 2; i <= N; ++i )
	{
		fin >> x;
		Ad[x].push_back(i);
	}
}

void Dfs( int nod, int depth )
{
	euler[++last] = nod;
	h[last] = depth;
	pos[nod] = last;

	int w;

	for( int i = 0; i < Ad[nod].size(); ++i )
	{
		w = Ad[nod][i];

		Dfs( w, depth + 1 );

		euler[++last] = nod;
		h[last] = depth;
	}
}

void Rmq()
{
	for( int i = 2; i <= last; ++i )
	  lg[i] = lg[i / 2] + 1;

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

	for( int i = 1; (1 << i) < last; ++i )
	  for( int j = 1; j <= last - (1 << i); ++j )
		{
		  int l = 1 << (i - 1);

		  rmq[i][j] = rmq[i - 1][j];
		  if(h[ rmq[i - 1][j + l] ] < h[ rmq[i][j] ] )
		    rmq[i][j] = rmq[i - 1][j + l];
		}
}

int lca(int x, int y)
{
	int diff, l, sol, sh;

	int a = pos[x], b = pos[y];

	if(a > b) swap( a, b );

	diff = b - a + 1;

	l = lg[diff];

	sol = rmq[l][a];

	sh = diff - ( 1 << l );
	if(h[sol] > h[ rmq[l][a + sh] ] )
	  sol = rmq[l][a + sh];

	return euler[sol];
}

int main()
{
	citire();

	Dfs(1, 0);
	Rmq();

	while(M--)
	{
	 int x, y;
	 fin >> x >> y;

	 fout << lca(x, y) << "\n";
	}
}