Cod sursa(job #481644)

Utilizator mottyMatei-Dan Epure motty Data 1 septembrie 2010 12:03:28
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 1.52 kb
#include<cstdio>
#include<vector>

using namespace std;

const int N=100002, M=21;

int n, m, lev[N], peu[N], mn[M][N*10], eu[N*10], poz;

vector <int> g[N];

void Read()
{
	int x;

	scanf("%d%d",&n,&m);
	
	for( int i=2; i<=n; ++i)
	{
		scanf("%d",&x);
		g[x].push_back(i);
	}
}

void Parc(int x)
{
	int sz=g[x].size();
	
	eu[++poz]=x;
	peu[x]=poz;
	
	for( int i=0; i<sz; ++i)
	{
		lev[g[x][i]]=lev[x]+1;
		Parc(g[x][i]);
		eu[++poz]=x;
	}
}

int GetPowMax(int x)
{
	int i=0;
	while( (1<<(i+1))<=x )
		++i;
	return i;
}

void GetMin( int i, int j)
{
	int a, b;
	a=mn[i-1][j];
	b=mn[i-1][j+(1<<(i-1))];
	mn[i][j]=(lev[a]<lev[b] ? a:b);
}

void ProbePrint()
{
	for( int i=0; i<=4; ++i,printf("\n"))
		for( int j=1; j<=poz; ++j)
			printf("%3d",lev[mn[i][j]]);
	
	printf("\n\n");
	
	for( int i=0; i<=4; ++i,printf("\n"))
		for( int j=1; j<=poz; ++j)
			printf("%3d",mn[i][j]);
}

void MakeRMQ()
{
	int PowMax=GetPowMax(poz);

	for( int i=1; i<=poz; ++i)
		mn[0][i]=eu[i];
	
	for( int i=1; i<=PowMax; ++i)
		for( int j=1; j<=poz-(1<<i)+1; ++j)
			GetMin( i, j);

	//ProbePrint();
}

void InteRMQ()
{
	int a, b, PowMax;
	
	while(m--)
	{
		scanf("%d%d",&a,&b);
		PowMax=GetPowMax(peu[b]-peu[a]+1);
		a=mn[PowMax][peu[a]];
		b=mn[PowMax][peu[b]-(1<<PowMax)+1];
		a= (lev[a]<lev[b] ? a:b);
		printf("%d\n",a);
	}
}

int main()
{
	freopen("lca.in","r",stdin);
	freopen("lca.out","w",stdout);
	
	Read();
	Parc(1);
	MakeRMQ();
	InteRMQ();
	
	return 0;
}