#include <stdio.h>
#include <stdlib.h>
#include <queue>
int a[1000000];
int mins[1000000];
int dfs_size;
struct node {
int value;
struct node *next;
};
struct list {
node *head;
};
list* create_list()
{
list *l = (list*)calloc(1, sizeof(list));
l->head = NULL;
return l;
}
void insert_list(list* l, int value, int weight)
{
if (l->head == NULL) {
l->head = (node*)calloc(1, sizeof(node));
l->head->value = value;
return;
}
node *p = l->head;
while (p->next != NULL)
p = p->next;
node *n = (node*)calloc(1, sizeof(node));
n->value = value;
p->next = n;
}
void destroy_list(list **l)
{
while ((*l)->head != NULL) {
node *p = (*l)->head;
(*l)->head = (*l)->head->next;
free(p);
}
}
enum colors {
WHITE = 0,
GRAY,
BLACK
};
struct tree {
int n;
list **adj;
int *positions;
};
tree* create_tree(int size)
{
tree *t = (tree*)calloc(1, sizeof(tree));
t->n = size;
t->adj = (list**)calloc(size, sizeof(list*));
t->positions = (int*)calloc(size, sizeof(int));
for (int i = 0; i < size; i++)
t->positions[i] = -1;
return t;
}
void add_tree_edge(tree *t, int v1, int v2, int w)
{
if (t->adj[v1] == NULL)
t->adj[v1] = create_list();
insert_list(t->adj[v1], v2, w);
}
void destroy_tree(tree **t)
{
for (int i = 0; i < (*t)->n; i++) {
if ((*t)->adj[i])
destroy_list(&((*t)->adj[i]));
}
free((*t)->adj);
free((*t)->positions);
free(*t);
}
void dfs(tree *t, int source)
{
if (t->positions[source] == -1)
t->positions[source] = dfs_size;
a[dfs_size++] = source;
node *n = NULL;
if (t->adj[source]) {
n = t->adj[source]->head;
while (n) {
dfs(t, n->value);
a[dfs_size++] = source;
n = n->next;
}
}
}
void initialize(int node, int b, int e)
{
if (b == e)
mins[node] = b;
else {
initialize(2 * node, b, (b + e) / 2);
initialize(2 * node + 1, (b + e) / 2 + 1, e);
mins[node] = (a[mins[2 * node]] < a[mins[2 * node + 1]]) ? mins[2 * node] : mins[2 * node + 1];
}
}
int query(int node, int b, int e, int i, int j)
{
if (e < i || j < b)
return -1;
if (i <= b && e <= j)
return mins[node];
int p1 = query(2 * node, b, (b + e) / 2, i, j);
int p2 = query(2 * node + 1, (b + e) / 2 + 1, e, i, j);
if (p1 == -1)
return p2;
if (p2 == -1)
return p1;
return (a[p1] < a[p2]) ? p1 : p2;
}
int main()
{
int n, m;
tree *t = NULL;
freopen("lca.in", "r", stdin);
freopen("lca.out", "w", stdout);
scanf("%d %d\n", &n, &m);
t = create_tree(n);
for (int i = 0; i < (n - 1); i++) {
int parent;
scanf("%d ", &parent);
add_tree_edge(t, parent - 1, i + 1, 0);
}
dfs_size = 0;
dfs(t, 0);
initialize(1, 0, dfs_size - 1);
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d\n", &u, &v);
int p1 = t->positions[u - 1];
int p2 = t->positions[v - 1];
int q = query(1, 0, dfs_size - 1, p1, p2);
printf("%d\n", a[q] + 1);
}
destroy_tree(&t);
return 0;
}