Cod sursa(job #3137506)

Utilizator thinkphpAdrian Statescu thinkphp Data 13 iunie 2023 09:17:01
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.91 kb
#include<stdio.h>
#define infile "lca.in"
#define outfile "lca.out"
#define nmax (100*1001)
#define lmax 18
struct lista
{
	int n,p; //nodul si pozitia
} l[nmax]; //lista arborelui
struct nod
{
	int p; //pozitia din lista
	int e; //prima pozitie in parcurgerea euleriana
	int h; //inaltimea nodului in arbore
}n[nmax];
int lg[nmax<<1]; //lg[i]=logaritm in baza 2 din i
int e[nmax<<1]; //parcurgerea euleriana
int rmq[lmax][nmax<<1]; //range minimum query pe parcurgerea euleriana
int nr; //numarul de noduri al arborelui
int k; //numarul de elemente ale parcurgerii euleriene
int q; //numarul de query-uri
int x; //variabila folosita in funtia lca

inline int lca(int i, int j)
{
	i=n[i].e;
	j=n[j].e;
	
	if(j<i) x=i,i=j,j=x;
	x=lg[j-i+1];
	
	i=rmq[x][i];
	j=rmq[x][j-(1<<x)+1];
	
	if(n[i].h < n[j].h)
		return i;
	else return j;
}

void read()
{
	int i,j;
	scanf("%d %d\n",&nr,&q);
	for(i=2;i<=nr;i++)
	{
		scanf("%d",&j); //tatal nodului i
		l[i].p=n[j].p; l[i].n=i; n[j].p=i; //adaugam in lista
	}
}

void dfs(int rad, int lvl)
{
	int i;
	
	e[++k]=rad; //salvam nodul in parcurgere
	n[rad].h=lvl; //salvam inaltimea nodului in arbore
	n[rad].e=k; //salvam prima aparitie a nodului in parcurgerea euleriana
	
	for(i=n[rad].p;i;i=l[i].p)
	{
		dfs(l[i].n,lvl+1); //parcurgem mai jos
		e[++k]=rad; //salvam din nou in parcurgere
	}
}

void init()
{
	int i,j,x,y;
	
	//initializam vectorul logaritmilor
	for(i=2;i<=k;i++)
		lg[i]=lg[i/2]+1;
	
	//initializam rmq
	for(i=1;i<=k;i++)
		rmq[0][i]=e[i];
	
	//construim rmq-ul
	for(i=1;(1<<i)<=k;i++)
		for(x=(1<<i),y=(1<<(i-1)),j=1;j+x-1<=k;j++)
		{
			rmq[i][j]=rmq[i-1][j];
			if(n[rmq[i-1][j+y]].h<n[rmq[i][j]].h)
				rmq[i][j]=rmq[i-1][j+y];
		}
}

void solve()
{
	int i,j;
	
	while(q--)
	{
		scanf("%d %d\n",&i,&j);
		printf("%d\n",lca(i,j));
	}
}

int main()
{
	freopen(infile,"r",stdin);
	freopen(outfile,"w",stdout);
	
	read();
	dfs(1,1);
	init();
	solve();
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}