Cod sursa(job #779144)

Utilizator danalex97Dan H Alexandru danalex97 Data 16 august 2012 19:39:37
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.93 kb
// Lca-ul a 2 noduri intr-un arbore este cel mai mic stramos comun.
// Problema se rezolva printr-o parcurgere Euler cu retinerea 
// nivelelor fiecarui element parcurs. Astfel minimul va fi 
// minimul elementelor de la First[i] la First[j] , First
// reprezentand prima aparitie a elementului i in parcurgerea
// Euler. Cu un RMQ complexitatea va fi O(N lg N+M) in timp
// si memorie. Cu un A-int compexitatea va fi O(N+M lg N) in
// timp si O(N) in memorie. 
// Parcurgerea Euler are maxim 4*N elemente.

#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

const int Nmax = 100011 ;
const int LgNx = 20 ;
const int Mmax = 2000011 ;

int N,M,L;

vector< int > V[Nmax];
int Rmq[LgNx][Nmax << 2];

int Lg[Nmax << 1];
int High[Nmax << 1];
int Lvl[Nmax << 1];
int First[Nmax];

ifstream F("lca.in");
ofstream G("lca.out");

void Get( int Nod , int Niv)
{
	High[ ++L ]=Nod;
	Lvl[ L ]=Niv;
	First[ Nod ]=L;
	
	for (int i=0;i<int( V[Nod].size() );++i)
	{	
		Get( V[Nod][i] , Niv+1 );
		High[ ++L ]=Nod;
		Lvl[ L ]=Niv;
	}
}

void Build()
{
	for (int i=1;i<=L;++i)
		Lg[i]=Lg[i>>1]+1;
	for (int i=1;i<=L;++i)
		Rmq[0][i]=Lvl[i];
	
	for (int i = 1; (1 << i) < L; ++i)
		for (int j = 1; j <= L - (1 << i); ++j)
		{
			int l = 1 << (i - 1);			
			Rmq[i][j] = Rmq[i-1][j];
			if ( Lvl[Rmq[i-1][j + l]] < Lvl[Rmq[i][j]] )
				Rmq[i][j] = Rmq[i-1][j + l];
		}
}

int LCA(int x, int y)
{
	int Difrence, l, Sol, Sift;
	
	int a = First[x]; 
	int b = First[y];
	if (a > b) swap(a, b);
	
	Difrence = b - a + 1;
	l = Lg[ Difrence ];
	
	Sol = Rmq[l][a];
	Sift = Difrence - (1 << l);
	
	if( Lvl[Sol] > Lvl[Rmq[l][a + Sift]] )
		Sol = Rmq[l][a + Sift];
	return High[Sol];
}

int main()
{
	F>>N>>M;
	for (int i=2;i<=N;++i)
	{
		int x;
		F>>x;
		V[x].push_back( i );
	}
	
	Get( 1,0 );
	Build();
	
	while ( M-- )
	{
		int x,y;
		F>>x>>y;
		G<<LCA( x,y )<<'\n';
	}
}