#include <iostream>
#include <fstream>
#define Nmax 100005
#define LogMaxN 17
#include <queue>
#include <math.h>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
queue <int> a[Nmax],b[Nmax];
int n,m; // numarul de noduri si nr de intrebari
int nivel[Nmax];// stochez nivelul pe care se afla nodul i
int viz[Nmax];// vector pentru stabilirea nivelelor fiecarui nod
int matrice[Nmax][LogMaxN]; // matrice folosita la precalculare rmq
int prima_aparitie[Nmax];
void Citire (int &n,int &m,queue <int> a[Nmax])
{
int i,x;
fin>>n>>m;
for (i = 2 ; i <= n ; i++)
{
fin>>x;
a[x].push(i);
b[x].push(i);
}
}
void Reprezentare_Euler (int x,queue <int> a[Nmax],int reprez_Euler[],int &k) // asemenea unei parcurgeri rsd doar ca afisez radacina si pe intoarcere
{
int i;
k++ ;
reprez_Euler[k]=x ;
while ( !a[x].empty() )
{
int y = a[x].front() ;
a[x].pop();
Reprezentare_Euler(y,a,reprez_Euler,k) ;
k++ ;
reprez_Euler[k]=x ;
}
}
void Stabilire_nivel_nod (int x,int tata,int nivel[],queue<int> a[Nmax],int viz[])
{
int i;
nivel[x]=nivel[tata]+1;
viz[x]=1;
while (!a[x].empty())
{
int y=a[x].front();
a[x].pop();
if (viz[y]==0)
Stabilire_nivel_nod(y,x,nivel,a,viz);
}
}
void Initializare_Prima_Aparitie (int euler[],int k,int prima_aparitie[])
{
int i;
for (i=1; i<=n; i++)
viz[i]=0;
for (i=1; i<=k; i++)
if (viz[euler[i]]==0)
{
prima_aparitie[euler[i]]=i;
viz[euler[i]]=1;
}
}
int nivel_min (int a,int b,int nivel[])
{
if (nivel[a]<nivel[b]) return a;
return b;
}
void precalculare_RMQ (int RMQ[Nmax][LogMaxN],int nivel[],int pozitie_e,int euler[])
{
for(unsigned int i=1; i<pozitie_e; i++)
{
RMQ[i][0]=euler[i];
}
for(unsigned int i=1; (1<<i)<=pozitie_e; i++)
{
for(unsigned int j=0; (1<<i)+j<pozitie_e; j++)
{
RMQ[j][i]=nivel_min(RMQ[j][i-1],RMQ[j+(1<<(i-1))][i-1],nivel);
}
}
}
/*
int logaritm (int x)
{
int nr=1;
while (1<<nr<=x) nr++;
nr--;
return nr;
}
*/
int query_RMQ (int a,int b,int nivel[],int RMQ[Nmax][LogMaxN])
{
int diferenta = b-a+1 ;
int k=(int)log2(diferenta);
int rest=diferenta-(1<<k);
return nivel_min( RMQ[a][k] , RMQ[a+rest][k] , nivel ) ;
}
int main()
{
int Parcurgere_Euler [5*Nmax],k=0, i ;
Citire( n, m,a ) ;
Reprezentare_Euler(1, a, Parcurgere_Euler, k ) ; ///stabilesc parcurgerea euler
nivel[0]=-1;
Stabilire_nivel_nod(1, 0, nivel, b, viz ) ; ///precalculez nivelul pe care se afla fiecare nod si stochez in vectorul nivel
precalculare_RMQ(matrice,nivel,k,Parcurgere_Euler);
Initializare_Prima_Aparitie(Parcurgere_Euler, k, prima_aparitie); /// stochez in vectorul prima aparitie pozitia la care apare prima data un nod in parcurgerea euler
/*
for (i=1;i<=k;i++)
fout<<i<<" ";
fout<<"\n";
for (i=1 ; i <= k ; i++ )
fout<<Parcurgere_Euler[i]<<" ";
fout<<"\n";
for (i=1; i<=k; i++)
fout<<nivel[Parcurgere_Euler[i]]<<" ";
fout<<"\n";
*/
for (i=1; i<=m; i++)
{
int a,b,mini,maxi;
fin>>a>>b;
mini=min(prima_aparitie[a],prima_aparitie[b]);
maxi=max(prima_aparitie[a],prima_aparitie[b]);
fout<<query_RMQ(mini,maxi,nivel,matrice)<<"\n";
}
return 0;
}