Cod sursa(job #678391)

Utilizator batistaUPB-Oprea-Cosmin-Dumitru batista Data 11 februarie 2012 16:49:53
Problema Lowest Common Ancestor Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 1.69 kb
#include<cstdio>
#define min(a,b) (a<b)?a:b
#define max(a,b) (a>b)?a:b
using namespace std;
int n,m,i,t,x,y,j,tata,a,b;
struct nod{int info; nod*adr;}*v[100003],*p;
int eul[200005],q,minn;
int niv[200005];
int poz[100005];
int arbint[1000005];
int nr[1000005];
void dfs(int nd,int k)
{
	nod*p=v[nd];
	eul[++q]=nd;
	poz[nd]=q;
	niv[q]=k;
	while(p)
	{
	  dfs(p->info,k+1);
	  eul[++q]=nd;
	  niv[q]=k;
	  p=p->adr;
	}
}

void update(int nod,int left,int right,int poz,int val)
{
	 if (left==right)
     {
		arbint[nod]=val;
		nr[nod]=eul[poz];
        return;
     }
     int mij=(left+right)/2;
     if (poz<=mij){ if(2*nod<400005)update(2*nod,   left,   mij,  poz, val);}
     else           if(2*nod<400005) update(2*nod+1, mij+1, right, poz, val);
	 if(arbint[2*nod]<arbint[2*nod+1])
	 {
		 arbint[nod]=arbint[2*nod];
		 nr[nod]=nr[2*nod];
	 }
	 else
	 {
		 arbint[nod]=arbint[2*nod+1];
		 nr[nod]=nr[2*nod+1];
	 }
}

void query(int nod,int left,int right,int a,int b)
{
	if (a<=left&& right<=b)
     {
		if (minn>arbint[nod]){ tata=nr[nod]; minn=arbint[nod]; }
        return;
     }
     int mij=(left+right)/2;
     if (a<=mij) query(2*nod,   left,   mij,  a, b);
     if (mij<b)  query(2*nod+1, mij+1, right, a, b);
}

int main()
{
	freopen ("lca.in","r",stdin);freopen ("lca.out","w",stdout);
	scanf("%d %d",&n,&m);
	for(i=2;i<=n;i++)
	{
		scanf("%d",&t);
		p=new nod;
		p->info=i; p->adr=v[t]; v[t]=p;
	}
	dfs(1,0);
	for(i=1;i<=2*n;i++)
		update(1,1,2*n,i,niv[i]);
	for(i=1;i<=m;i++)
	{
		minn=200000000;
		scanf("%d %d",&x,&y);
		b=max(poz[x],poz[y]);
		a=min(poz[x],poz[y]);
		query(1,1,2*n,a,b);
		printf("%d\n",tata);
	}
	
return 0;}