Pagini recente » Cod sursa (job #3215512) | Cod sursa (job #1255972) | Cod sursa (job #1396099) | Cod sursa (job #537945) | Cod sursa (job #2120969)
#include <iostream>
#include <fstream>
#include <vector>
#define DM 100005
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, u, v, dim, eul[DM*2], lvl[DM*2], first[DM*2], rmq[20][DM*2], log[DM*2];
vector <int> g[DM];
void dfs(int nod, int level)
{
dim++;
eul[dim]=nod;
lvl[dim]=level;
first[nod]=dim;
for(auto it:g[nod])
{
dfs(it,level+1);
dim++;
eul[dim]=nod;
lvl[dim]=level;
}
}
void build_rmq()
{
//in rmq[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui
log[0]=-1;
for(int i=1;i<=dim;i++)
log[i]=1+log[i>>1];
for(int i=1;i<=dim;i++)
rmq[0][i]=i;
for(int k=1;k<=log[dim];k++)
for(int i=1;i<=dim-(1<<k);i++)
{
int l=(1<<(k-1));
if(lvl[rmq[k-1][i+l]] < lvl[rmq[k-1][i]])
rmq[k][i]=rmq[k-1][i+l];
else rmq[k][i]=rmq[k-1][i];
}
}
int lca(int u, int v)
{
//Cel mai apropiat strămoş comun a 2 noduri este nodul de nivel minim dintre primele apariţii ale nodurilor din query din reprezentarea Euler a arborelui.
int l, i, rez;
u=first[u];
v=first[v];
if(u>v)
swap(u,v);
l=log[v-u+1];
if(lvl[rmq[l][u]] < lvl[rmq[l][v-(1<<l)+1]])
return eul[rmq[l][u]];
else return eul[rmq[l][v-(1<<l)+1]];
}
int main()
{
fin>>n>>m;
for(int i=2;i<=n;i++)
{
fin>>u;
g[u].push_back(i);
}
dfs(1,0);
build_rmq();
/*for(int k=0;k<=log[dim];k++)
{for(int i=1;i<=dim;i++) cout<<rmq[k][i]<<' '; cout<<endl;}*/
for(int i=1;i<=m;i++)
{
fin>>u>>v;
fout<<lca(u,v)<<'\n';
}
return 0;
}