#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<typename T>
using oset = tree<T, null_type, less<T>,
rb_tree_tag, tree_order_statistics_node_update>;
#ifdef Wi_TEST
template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1,T2> p) {
out << "(" << p.first << ", " << p.second << ")";
out.flush();
return out;
}
#define deb(x) cout << #x << " = " << x << endl;
#else
#define deb(x)
#define cin fin
#define cout fout
#endif
#define N 100005
pair<int, int> aint[4*N];
void update(int nod, int st, int dr, int poz, pair<int, int>& val) {
if(st == dr)
aint[nod] = val;
else {
int mij = (st + dr) >> 1;
if(poz <= mij)
update(nod*2, st, mij, poz, val);
else
update(nod*2+1, mij+1, dr, poz, val);
if(aint[nod*2].second < aint[nod*2+1].second) {
aint[nod] = aint[nod*2];
} else {
aint[nod] = aint[nod*2+1];
}
}
}
pair<int, int> query(int nod, int st, int dr, int l, int r) {
if(l <= st && dr <= r)
return aint[nod];
else {
int mij = (st + dr) >> 1;
pair<int, int> rez{-1, -1}, aux;
if(l <= mij)
rez = query(2*nod, st, mij, l, r);
if(r > mij) {
aux = query(2*nod+1, mij+1, dr, l, r);
if(rez.first == -1)
rez = aux;
else {
if(rez.second > aux.second)
rez = aux;
}
}
return rez;
}
}
vector<int> gc[N];
vector< pair<int, int> > rez;
int fiof[N];
void DFS(int x, int lvl = 0) {
rez.push_back({x, lvl});
for(int& aux : gc[x]) {
DFS(aux, lvl+1);
rez.push_back({x, lvl});
}
}
int main() {
ios_base::sync_with_stdio(false);
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, x;
cin >> n >> m;
for(int i = 2; i <= n; ++i){
cin >> x;
gc[x].push_back(i);
}
DFS(1);
for(int i = 0; i < rez.size(); ++i) {
update(1, 1, 2*n-1, i, rez[i]);
// if(!fiof[rez[i].first])
fiof[rez[i].first] = i;
// deb(rez[i]);
// deb(fiof[rez[i].first]);
}
fiof[1] = 0;
while(m--) {
int a, b;
cin >> a >> b;
a = fiof[a];
b = fiof[b];
if(a > b) swap(a, b);
cout << query(1, 1, 2*n-1, a, b).first << '\n';
}
return 0;
}