Cod sursa(job #643719)

Utilizator ELHoriaHoria Cretescu ELHoria Data 4 decembrie 2011 12:14:31
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 1.51 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int MAXN = 100005 , INF = int(2e9);
vector<int> G[MAXN];
int N ,  M , H[MAXN<<1] , L[MAXN<<1] , First[MAXN<<1] , K , sol , hsol;
int Arb[MAXN<<4] , start , finish;

void dfs(int node,int lev)
{
	H[++K] = node;  L[K] = lev; First[node] = K;
	for(vector<int>::const_iterator w = G[node].begin();w!=G[node].end();++w)
	{
		dfs(*w,lev + 1);
		H[++K] = node; L[K] = lev;
	}
}

void build(int root,int left,int right)
{
	if(left == right)
	{
		Arb[root] = left;
		return;
	}
	int lson = 2*root , rson = 2*root + 1 , mij = (left + right)>>1;
	build(lson,left,mij);
	build(rson,mij + 1,right);
	if(L[Arb[lson]] <= L[Arb[rson]])
		Arb[root] = Arb[lson];
	else
		Arb[root] = Arb[rson];
}

void query(int root,int left,int right)
{
	if(start<=left && right<=finish)
	{
		if( hsol > L[Arb[root]])
		sol = H[Arb[root]] , hsol = L[Arb[root]];
		return;
	}
	int lson = 2*root , rson = 2*root + 1 , mij = (left + right)>>1;
	if(start <= mij) query(lson,left,mij);
	if(mij < finish) query(rson,mij + 1,right);
}

int lca(int x,int y)
{
	start = First[x] , finish = First[y];
	if(start > finish) swap(start,finish);
	sol = hsol = INF;
	query(1,1,K);
	return sol;
}

int main()
{
	fin>>N>>M;
	for(int i = 2;i<=N;++i)
	{
		int x ;
		fin>>x;
		G[x].push_back(i);
	}
	dfs(1,0);
	build(1,1,K);
	for(;M;M--)
	{
		int x , y;
		fin>>x>>y;
		fout<<lca(x,y)<<'\n';
	}
	return 0;
}