#include<bits/stdc++.h>
using namespace std;
ifstream F("lca.in");
ofstream G("lca.out");
#define L(x) ((x)&-(x))
const int N=1e5,M=1<<10;
char b[M],c[M];
int p=M,q,r[N-1],h[N],d[N],e[N],f[N],g[N],s[2*N+1],n,m,x;
inline char A()
{
if(p==M)
F.read(b,M),p=0;
return b[p++];
}
inline int B()
{
int q=0;
char c;
for(c=A();!isdigit(c);c=A());
for(;isdigit(c);q=(q<<1)+(q<<3)+(c-'0'),c=A());
return q;
}
inline void C(char& c)
{
c[q++]=c;
if(q==M)
G.write(c,M),q=0;
}
inline void D(int x)
{
int q;
int n=0;
char o[6];
do
q=(3435973837LL*x)>>35,o[n++]=x-(q<<1)-(q<<3)+'0',x=q;
while(x);
for(;n--;C(o[n]));
C('\n');
}
void E(const int n)
{
static int parent[N],vertices[N];
int stackSize=1,currIdx=1;
while(stackSize) {
const int node=vertices[--stackSize];
d[node]=currIdx++;
for(int i=h[node];~i;i=r[i]) {
const int son=i+1;
parent[son]=node;
vertices[stackSize++]=son;
}
}
int queueFront=0,queueBack=1;
vertices[0]=0;
while(queueBack!=queueFront) {
const int node=vertices[queueFront++];
for(int i=h[node];~i;i=r[i]) {
const int son=i+1;
vertices[queueBack++]=son;
}
}
memcpy(e,d,4*n);
for(int i=n-1;i>=0;i-=1) {
const int node=vertices[i];
if(L(e[parent[node]])<L(e[node])) {
e[parent[node]]=e[node];
}
}
f[0]=0;
for(int i=0;i<n;i+=1) {
f[vertices[i]]=f[parent[vertices[i]]]|L(e[vertices[i]]);
}
g[d[0]-1]=0;
for(int i=0;i<n;i+=1) {
const int node=vertices[i];
for(int j=h[node];~j;j=r[j]) {
const int son=j+1;
if (e[node]!=e[son]) {
g[d[son]-1]=node;
} else {
g[d[son]-1]=g[d[node]-1];
}
}
}
}
inline int Q(const int& x,const int& y)
{
const int I=e[x],J=e[y];
const int U=L(I),V=L(J);
const int Z=s[(I^J)|U|V];
const int W=L(f[x]&f[y]&~Z),K;
int X,Y;
W!=U?K=s[f[x]&(W-1)],X=g[((d[x]&~K)|(K+1))-1]:X=x;
W!=V?K=s[f[y]&(W-1)],Y=g[((d[y]&~K)|(K+1))-1]:Y=y;
return d[X]<d[Y]?X:Y;
}
int main()
{
for(n=B(),m=B(),memset(h,-1,4*n),i=1;i<n;x=B()-1,r[i-1]=h[x],h[x]=i-1,++i);
for(s[1]=0,i=2;i<=n+n;(i&(i-1)?s[i]=s[i-1]:s[i]=((s[i-1]+1)<<1)-1,++i);
for(E(n);m--;D(1+Q(B()-1,B()-1));
return G.write(c,q),0;
}