Cod sursa(job #1197185)

Utilizator Kira96Denis Mita Kira96 Data 10 iunie 2014 23:53:31
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.44 kb
#include<fstream>
#include<cstdio>
#include<set>
#include<stack>
#define ROF(a,b,c) for(int a=b;a>=c;--a)
#include<vector>
#include<algorithm>
#define FOR(a,b,c) for(int a=b;a<=c;++a)
#define FIT(it,e) for(vector<int>::iterator it=e.begin();it!=e.end();it++)
#include<cstring>
#include<bitset>
#include<cmath>
#include<iomanip>
#include<queue>
#define debug printf("OK!\n");
#define f cin
#define g cout
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ll unsigned long long
#define mod 666013
#define N 100100
#define LM 17
#define DIM 1000100
#define infile "lca.in"
#define outfile "lca.out"
using namespace std;
//int dx[]={0,0,0,1,-1};
//int dy[]={0,1,-1,0,0};
ifstream f(infile);
ofstream g(outfile);
vector<int> v[N],P[N];
int arb[N],T[N],F[LM][N],niv[N],t,s[N],lvl[N],poz[N],nrl,lant[N],n,q,x,a,b;
void dfs(int x,int p,int lvl)
{
	T[x]=p;
	niv[x]=lvl;
	arb[x]=1;
	
	int best=0;
	
	FIT(it,v[x])
	{
		if(!niv[*it])
		{
			dfs(*it,x,lvl+1);
			arb[x]+=arb[*it];
			if(arb[*it]>arb[best])
				best=*it;
		}
	}
	
	if(best)
	{
		lant[x]=lant[best];
		P[lant[x]].pb(x);
		poz[x]=P[lant[x]].size();
	}
	else
	{
		++nrl;
		P[nrl].pb(0);
		P[nrl].pb(x);
		poz[x]=1;
		lant[x]=nrl;
	}
}
void dfs1(int x,int p)
{
	if(poz[x]==1)
	{
		int p2=0;
		for(int po=1;po<=t;po<<=1,p2++)
			F[p2][x]=s[t-po+1];
		s[++t]=x;
		lvl[x]=t;
	}
	
	FIT(it,v[x])
		if(*it!=p)
			dfs1(*it,x);
	
	if(poz[x]==1)
		--t;
}
int lca(int a,int b)
{
	if(lant[a]==lant[b])
	{
		if(poz[a]<poz[b])
			return a;
		return b;
	}
	
	a=P[lant[a]][1];
	b=P[lant[b]][1];
	
	if(lvl[a]>lvl[b])
		swap(a,b);
	int dif=lvl[b]-lvl[a];
	int po=1;
	int t=0;
	
	for(;po<=dif;po<<=1,t++);
	po>>=1;
	t--;
	
	for(;dif;po>>=1,t--)
	{
		if(po<=dif)
		{
			dif-=po;
			b=F[t][b];
		}
	}
	
	for(po=1,t=0;po<=lvl[a];po<<=1,t++);
	po>>=1;
	t--;
	
	for(;po;po>>=1,t--)
	{
		if(F[t][a]!=F[t][b])
		{
			a=F[t][a];
			b=F[t][b];
		}
	}
	if(lant[a]==lant[b])
	{
		if(poz[a]<poz[b])
			return a;
		return b;
	}
	a=T[a];
	b=T[b];
	if(poz[a]<poz[b])
		return a;
	return b;
}
	
int main ()
{
	f>>n>>q;
	FOR(i,2,n)
	{
		f>>x;
		v[x].pb(i);
	}
	dfs(1,0,1);
	FOR(i,1,nrl)
	{
		int siz=P[i].size();
		FOR(j,1,siz/2)
		{
			swap(P[i][j],P[i][siz-j]);
			swap(poz[P[i][j]],poz[P[i][siz-j]]);
		}
	}
	dfs1(1,0);
	FOR(i,1,q)
	{
		f>>a>>b;
		g<<lca(a,b)<<"\n";
	}
	return 0;
}