#include <fstream>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 1 + 1e5, BB = 16, LG = 14;
const int Size = BB + 2 * N / BB;
class OptimalLCA{
int son[N], bro[N], depth[N];
int euler[2 * N + 2 * BB], position[N];
int bMask[1 << BB], bucket[Size], n;
int rmq[LG][Size];
void dfs(int x, int T){
depth[x] = 1 + depth[T];
euler[ ++euler[0] ] = x;
position[x] = euler[0];
for (int i = son[x] ; i ; i = bro[i]){
dfs(i, x);
euler[ ++euler[0] ] = x;
}
}
void computeMask(int p, int mask, int val, int best, int bestVal){
bMask[ mask ^ (1 << p) ] = best;
if (p + 1 != BB){
computeMask(p + 1, mask, val - 1, best, bestVal);
++val;
if (bestVal < val)
computeMask(p + 1, mask ^ (1 << p), val, p + 1, val);
else
computeMask(p + 1, mask ^ (1 << p), val, best, bestVal);
}
}
int getBucket(int st, int dr){
int ans = 0;
for (int i = st + 1, sw = 1 ; i < dr ; i++, sw <<= 1)
if ( depth[ euler[i] ] < depth[ euler[i - 1] ] )
ans ^= sw;
return ans;
}
inline int best(int x, int y){
return depth[x] < depth[y] ? x : y;
}
inline int best(int x, int y, int z){
return best( best(x, y), z );
}
inline int maskQuery(int x, int y){
int L = 1 << (y - x), mask = (bucket[x >> 4] >> (x & 15) ) & (L - 1);
return euler[ x + bMask[ mask ^ L ] ];
}
inline int rmqQuery(int x, int y){
if (y < x) return 0;
int L = 31 - __builtin_clz(y - x);
return best( rmq[L][x], rmq[L][ y - (1 << L) + 1 ] );
}
public:
void build(int T[], int n){
memset(son, 0, sizeof(son));
memset(bro, 0, sizeof(bro));
this -> n = n;
euler[0] = 0;
for (int i = 2 ; i <= n ; i++){
if ( son[ T[i] ] )
bro[i] = son[ T[i] ];
son[ T[i] ] = i;
}
dfs(1, 0);
computeMask(0, 0, 0, 0, 0);
int size = 1 + (n >> 3);
for (int i = 0 ; i <= size ; i++){
bucket[i] = getBucket(i << 4, (i + 1) << 4);
rmq[0][i] = euler[ (i << 4) + bMask[ bucket[i] ^ 32768 ] ];
}
depth[0] = n;
for (int i = 1, step = 1 ; i < LG ; i++, step <<= 1)
for (int j = 1 ; j + step <= size ; j++)
rmq[i][j] = best(rmq[i - 1][j], rmq[i - 1][j + step]);
}
int lca(int x, int y){
x = position[x];
y = position[y];
if (y < x) swap(x, y);
int pX = x >> 4, pY = y >> 4;
if (pX == pY)
return maskQuery(x, y);
return best( maskQuery(x, ( (pX + 1) << 4) - 1), rmqQuery(pX + 1, pY - 1), maskQuery( pY << 4, y ) );
}
};
#include <iostream>
OptimalLCA tree;
int T[N];
int main(){
int nrQ, n, x, y;
ifstream in("lca.in");
in >> n >> nrQ;
for (int i = 2 ; i <= n ; i++)
in >> T[i];
tree.build(T, n);
ofstream out("lca.out");
while (nrQ--){
in >> x >> y;
out << tree.lca(x, y) << '\n';
}
in.close();
out.close();
cout << 1.0 * sizeof(tree) / ( 1 << 20 ) << " MB" << '\n';
return 0;
}