Pagini recente » Cod sursa (job #1887826) | Cod sursa (job #1444026) | Cod sursa (job #3239246) | Monitorul de evaluare | Cod sursa (job #3137506)
#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;
}