Cod sursa(job #661352)

Utilizator ELHoriaHoria Cretescu ELHoria Data 14 ianuarie 2012 13:01:34
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 1.32 kb
#include <fstream>
#include <vector>

using namespace std;

typedef vector<int> VI;
typedef VI::const_iterator CIT;

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

const int NMAX = 100005 , MAXL = 20;
VI G[NMAX];
int N , Q , K , x , y;
int rmq[MAXL][NMAX] , H[NMAX<<1] , Lev[NMAX<<1] , First[NMAX<<1] , Lg[NMAX<<1];

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

void df(int node,int lev)
{
	H[++K] = node; Lev[K] = lev;
	rmq[0][K] = First[node] = K;
	for(CIT w = G[node].begin();w != G[node].end();++w)
	{
		df(*w,lev + 1);
		H[++K] = node; Lev[K] = lev;
		rmq[0][K] = K;
	}
}

void RMQ()
{ 
	for(int i = 2; i <= K; ++i)
		Lg[i] = Lg[i >> 1] + 1;

	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(Lev[rmq[i-1][j + l]] < Lev[rmq[i][j]])
				rmq[i][j] = rmq[i-1][j + l];
		}
}

int lca(int x,int y)
{
	x = First[x] , y = First[y]; if(x > y) swap(x,y);
	int dif = y - x + 1 ;
	int l = Lg[dif] , sh = dif - (1<<Lg[dif]);
	return Lev[ rmq[l][x] ] < Lev[ rmq[l][x + sh] ] ?  H[ rmq[l][x] ] : H[ rmq[l][x + sh] ];
}

int main()
{
	read_data();
	df(1,0);
	RMQ();
	for(;Q;Q--) 
	{
		fin>>x>>y;
		fout<<lca(x,y)<<'\n';
	}
	return 0;
}