Cod sursa(job #654341)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 30 decembrie 2011 12:06:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.83 kb
#include<fstream>
#include<vector>
#include<iostream>
using namespace std;
int n,m,poz[100100],N,rmq[200100][20],minpoz[201000][20],put[200100];
vector <int> fiu[100100],euler,adancime;
vector <int>::iterator it;

inline void DFS(int nod,int niv)
{
	vector <int>::iterator it;
	for(it=fiu[nod].begin();it!=fiu[nod].end();it++)
	{
		euler.push_back(nod);
		adancime.push_back(niv);
		poz[nod]=N++;
        DFS(*it,niv+1);
	}
	euler.push_back(nod);
	adancime.push_back(niv);
	poz[nod]=N++;
}

inline void Precalculare_RMQ()
{
	int i,k,lim,lg;
	put[1]=0;
	for(i=2;i<=N;i++)
		put[i]=put[i/2]+1;
	for(i=1;i<=N;i++)
	{
		rmq[i][0]=adancime[i];
		minpoz[i][0]=i;
	}
	for(k=1;(1<<k)<=N;k++)
	{
		lim=N-(1<<k)+1;
		for(i=1;i<=lim;i++)
		{
			lg=(1<<(k-1));
			if(rmq[i][k-1]<rmq[i+lg][k-1])
			{
				rmq[i][k]=rmq[i][k-1];
				minpoz[i][k]=minpoz[i][k-1];
			}
			else
			{
				rmq[i][k]=rmq[i+lg][k-1];
				minpoz[i][k]=minpoz[i+lg][k-1];
			}
		}
	}
}

int main()
{
	int i,tata,x,y,st,dr,lg,dif,exp;
	ifstream fin("lca.in");
	ofstream fout("lca.out");
	fin>>n>>m;
	for(i=2;i<=n;i++)
	{
		fin>>tata;
		fiu[tata].push_back(i);
	}
	// adaug pe pozitia 0 elemente fictive
	euler.push_back(0);
	adancime.push_back(0);
	N=1;
	//
	DFS(1,1); //fac parcurgere euler si construiesc si vectorul de adancimi
	N--;
	Precalculare_RMQ(); //fac RMQ pentru vectorul de adancimi
	//intrucat LCA(i,j)=nodul cu cea mai mica adancime din parcurgerea euler dintre nodurile i si j

	for(i=1;i<=m;i++)
	{
		fin>>x>>y;
		st=min(poz[x],poz[y]);
		dr=max(poz[x],poz[y]);
		lg=dr-st+1;
		exp=put[lg];
		dif=lg-(1<<exp);
		if(rmq[st][exp]<rmq[st+dif][exp])
		{
			fout<<euler[minpoz[st][exp]]<<"\n";
		}
		else
		{
			fout<<euler[minpoz[st+dif][exp]]<<"\n";
		}
	}
	
	fin.close();
	fout.close();
	return 0;
}