#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
ifstream is ("lca.in");
ofstream os ("lca.out");
const int Nmax = 200001;
const int Lmax = 20;
const int INF = 0x3f3f3f3f;
int N, Q;
int Euler[Nmax<<1], Depth[Nmax<<1], Ind[Nmax], K, Log[Nmax<<1];
int RMQ[Lmax][Nmax];
vector <int> Tree[Nmax];
bool Vis[Nmax];
void Read();
inline void DFS(int node, int);
void RangeMinimumQuery();
inline int LCA(int A, int B);
inline int Distance(int A, int B);
int main()
{
Read();
DFS(1, 1);
RangeMinimumQuery();
for (int R, X, Y, Z, sol, node; Q; --Q)
{
is >> X >> Y;
os << LCA(X, Y) << '\n';
/*is >> R >> X >> Y;
Z = LCA(X, Y);
sol = Distance(R, Z) + Distance(X, Z) + Distance(Y, Z), node = Z;
Z = LCA(X, R);
if (sol > Distance(R, Z) + Distance(X, Z) + Distance(Y, Z))
sol = Distance(R, Z) + Distance(X, Z) + Distance(Y, Z), node = Z;
Z = LCA(R, Y);
if (sol > Distance(R, Z) + Distance(X, Z) + Distance(Y, Z))
sol = Distance(R, Z) + Distance(X, Z) + Distance(Y, Z), node = Z;
cout << node << '\n';*/
}
}
void Read()
{
is >> N;
is >> Q;
for (int i = 2, x, y; i <= N; ++i)
{
is >> x;
Tree[x].push_back(i);
Tree[i].push_back(x);
}
};
inline void DFS(int node, int lvl)
{
Vis[node] = 1;
Ind[node] = ++K;
Euler[K] = node;
Depth[K] = lvl;
for (const int& next : Tree[node])
if (Vis[next] == 0)
{
DFS(next, lvl+1);
Euler[++K] = node;
Depth[K] = lvl;
}
}
void RangeMinimumQuery()
{
for (int i = 1; i <= K; ++i)
RMQ[0][i] = i;
for (int i = 2; i <= K; ++i)
Log[i] = Log[i >> 1] + 1;
for (int i = 1, k; (1 << i) <= K; ++i)
for (int j = 1; j + (1 << i) <= K+1; ++j)
if (Depth[RMQ[i-1][j]] <= Depth[RMQ[i-1][j+(1 << (i-1))]])
RMQ[i][j] = RMQ[i-1][j];
else
RMQ[i][j] = RMQ[i-1][j+(1 << (i-1))];
};
inline int LCA(int x, int y)
{
int p1 = Ind[x], p2 = Ind[y];
if (p1 > p2) swap(p1, p2);
int k = Log[p2-p1];
if (Depth[RMQ[k][p1]] <= Depth[RMQ[k][p2 - (1 << k) + 1]])
return Euler[RMQ[k][p1]];
return Euler[RMQ[k][p2 - (1 << k) + 1]];
};
inline int Distance(int A, int B)
{
return Depth[B] + Depth[A] - 2 * Depth[LCA(A, B)];
};