Cod sursa(job #513629)

Utilizator ChallengeMurtaza Alexandru Challenge Data 16 decembrie 2010 15:13:07
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.79 kb
#include <fstream>
#include <cstdio>
#include <vector>

using namespace std;

const char InFile[]="lca.in";
const char OutFile[]="lca.out";
const int MaxN=100111;
const int LogMaxN=21;

ifstream fin(InFile);
FILE *fout=fopen(OutFile,"w");

vector<int> a[MaxN];
int x,y,n,q,k,ep[MaxN],en[2*MaxN],eh[2*MaxN],rmq_min[LogMaxN][2*MaxN],rmq_pos[LogMaxN][2*MaxN],lg[2*MaxN];

void euler(int nod)
{
	++k;
	eh[++eh[0]]=k;
	en[++en[0]]=nod;
	ep[nod]=en[0];
	for(vector<int>::iterator it=a[nod].begin();it!=a[nod].end();++it)
	{
		euler(*it);
		eh[++eh[0]]=k;
		en[++en[0]]=nod;
	}
	--k;
}

inline void rmq()
{
	for(register int i=2;i<=eh[0];++i)
	{
		lg[i]=lg[i>>1]+1;
	}

	for(register int i=1;i<=eh[0];++i)
	{
		rmq_min[0][i]=eh[i];
		rmq_pos[0][i]=i;
	}

	int p=1;
	for(register int j=1;j<LogMaxN;++j,p<<=1)
	{
		for(register int i=1;i<=eh[0];++i)
		{
			if(i+p<=eh[0])
			{
				if(rmq_min[j-1][i]<rmq_min[j-1][i+p])
				{
					rmq_min[j][i]=rmq_min[j-1][i];
					rmq_pos[j][i]=rmq_pos[j-1][i];						
				}
				else
				{
					rmq_min[j][i]=rmq_min[j-1][i+p];
					rmq_pos[j][i]=rmq_pos[j-1][i+p];
				}
			}
			else
			{
				rmq_min[j][i]=rmq_min[j-1][i];
				rmq_pos[j][i]=rmq_pos[j-1][i];
			}
		}
	}
}

inline int lca(int x,int y)
{
	int st=min(ep[x],ep[y]);
	int sf=max(ep[x],ep[y]);
	int len=sf-st+1;
	int sol;
	if(rmq_min[lg[len]][st]<rmq_min[lg[len]][sf-(1<<lg[len])+1])
	{
		sol=rmq_pos[lg[len]][st];
	}
	else
	{
		sol=rmq_pos[lg[len]][sf-(1<<lg[len])+1];
	}
	return en[sol];
}

int main()
{
	fin>>n>>q;
	for(register int i=2;i<=n;++i)
	{
		fin>>x;
		a[x].push_back(i);
	}

	euler(1);
	rmq();

	for(register int i=0;i<q;++i)
	{
		fin>>x>>y;
		fprintf(fout,"%ld\n",lca(x,y));
	}
	fclose(fout);
	fin.close();
	return 0;
}