Cod sursa(job #2604689)

Utilizator betybety bety bety Data 23 aprilie 2020 11:52:46
Problema Aria Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2 kb
#include <vector>

#include <fstream>



using namespace std;



#define MAX_N 100005

#define MAX_L 20



#define foreach(V) for(auto it = (V).begin(); it != (V).end(); ++it)



int K, N, M;

int L[MAX_N << 1], H[MAX_N << 1],Lg[MAX_N << 1], First[MAX_N];

int Rmq[MAX_L][MAX_N << 2];



vector <int> G[MAX_N];



ifstream fin ("lca.in");

ofstream fout ("lca.out");



void citire()

{

	fin >> N >> M;



	for(int i = 2; i <= N; ++i)

	{

		int x;

		fin >> x;

		G[x].push_back(i);

	}

}



void dfs(int nod, int lev)

{

	H[++K] = nod; //nodul actual este adaugat in reprezentarea Euler a arborelui

	L[K] = lev; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui

	First[nod] = K; //se retine si prima aparitie a fiecarui nod in reprezentarea Euler a arborelui



	foreach(G[nod])

	{

		dfs(*it, lev+1);



		H[++K] = nod;

		L[K] = lev;

	}

}



void rmq()

{

//in Rmq[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui

	for(int i = 2; i <= K; ++i)

		Lg[i] = Lg[i >> 1] + 1;

	for(int i = 1; i <= K; ++i)

		Rmq[0][i] = i;



	for(int i = 1; (1 << i) < K; ++i)

		for(int j = 1; j <= K - (1 << i); ++j)

		{

			int l = 1 << (i - 1);



			Rmq[i][j] = Rmq[i-1][j];

			if(L[Rmq[i-1][j + l]] < L[Rmq[i][j]])

				Rmq[i][j] = Rmq[i-1][j + l];

		}

}



int lca(int x, int y)

{

//LCA-ul nodurilor x si y va fi nodul cu nivel minim din secventa (First[x], First[y]) din reprezentarea Euler a arborelui

	int diff, l, sol, sh;

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

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

	diff = b - a + 1;

	l = Lg[diff];

	sol = Rmq[l][a];

	sh = diff - (1 << l);

	if(L[sol] > L[Rmq[l][a + sh]])

		sol = Rmq[l][a + sh];

	return H[sol];

}



int main()

{

	citire();

	dfs(1, 0);

	rmq();



	while(M--)

	{

		int x, y;

		fin >> x >> y;

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

	}

}