Cod sursa(job #615869)

Utilizator paul_gabryelPaul Buda paul_gabryel Data 11 octombrie 2011 08:57:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.11 kb

#include <cstdio>
#include <fstream>
#include <vector>

using namespace std;

ifstream in ("lca.in");

#define N 100001

vector<int> v[N];
int n,m,k,lg[N<<1],rmq[32][N<<1],lvl[N<<1],h[N<<1],poz[N];

void read (){
	in>>n>>m;
	for(int j,i=2;i<=n;++i){
		in>>j;
		v[j].push_back(i);
		}
	}
	
void df (int nd,int lv){
	h[++k]=nd;
	lvl[k]=lv;
	poz[nd]=k;
	for(vector<int>::iterator it=v[nd].begin();it<v[nd].end();++it){
		df(*it,lv+1);
		h[++k]=nd;
		lvl[k]=lv;
		}
	}

void dinam (){
	rmq[0][1]=1;
	for(int i=2;i<=k;++i){
		lg[i]=lg[i>>1]+1;
		rmq[0][i]=i;
		}
	for(int i=1;(1<<i)<k;++i){
		for(int j=1;j+(1<<i)<=k;++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 a=poz[x],b=poz[y],sol,s,dif,l;
	if(a>b)
		swap(a,b);
	dif=b-a+1;
	l=lg[dif];
	sol=rmq[l][a];
	s=dif-(1<<l);
	if(lvl[sol]>lvl[rmq[l][a+s]])
		sol=rmq[l][a+s];
	return h[sol];
	}

void out (){
	freopen ("lca.out","w",stdout);
	for(int x,y;m;--m){
		in>>x>>y;
		printf("%d\n",lca(x,y));
	}
	}

int main ()
{
	read ();
	df (1,0);
	dinam ();
	out ();
	return 0;}