#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node *next;
};
int segtree_get_size(int n)
{
for (int i = 0; i <= 31; i++) {
int x = 0x1 << i;
if(x >= n)
return x;
}
return -1;
}
int list_add_front(struct node **head, int val)
{
struct node *tmp;
tmp = malloc(sizeof(struct node));
tmp->data = val;
tmp->next = *head;
*head = tmp;
}
int dfs(struct node **tree, int root, int *eul, int *lev, int *idx, int level, int* i)
{
eul[*i] = root;
lev[*i] = level;
idx[root] = *i;
(*i)++;
for(struct node *p = tree[root]; p != NULL; p = p->next) {
dfs(tree, p->data, eul, lev, idx, level+1, i);
eul[*i] = root;
lev[*i] = level;
(*i)++;
}
return 0;
}
void st_helper(int *segtree, int* array, int pos, int l, int r)
{
int mid = (l + r) / 2;
if (l == r) {
segtree[pos] = l;
return;
}
st_helper(segtree, array, 2 * pos, l, mid);
st_helper(segtree, array, 2 * pos+1, mid+1, r);
if (array[segtree[2 * pos]] < array[segtree[2 * pos + 1]])
segtree[pos] = segtree[2 * pos];
else
segtree[pos] = segtree[2 * pos + 1];
return;
}
int get_min(int *segtree, int *array, int pos, int l, int r, int x, int y)
{
int mid = (l + r) / 2;
int m1, m2;
if (x == l && y == r)
return segtree[pos];
// x y to the left
if (x >= l && y <= mid)
return get_min(segtree, array, 2 * pos, l, mid, x, y);
//x y to the right
if(x >= mid+1 && y <= r)
return get_min(segtree, array, 2 * pos + 1, mid+1, r, x, y);
//x in left y in right
m1 = get_min(segtree, array, 2 * pos, l, mid, x, mid);
m2 = get_min(segtree, array, 2 * pos + 1, mid+1, r, mid+1, y);
if(array[m1] < array[m2])
return m1;
else
return m2;
return -1;
}
void st_create(int **segtree, int* array, int n)
{
int sn = 2 * segtree_get_size(n);
*segtree = malloc((sn+1) * sizeof(int));
for (int i = 0; i <= sn; i++)
(*segtree)[i] = -1;
st_helper(*segtree, array, 1, 0, n-1);
}
int main()
{
FILE *infile, *outfile;
int n, m, i;
struct node **tree;
int *euler, *level, *index;
int *segtree;
int count = 0;
infile = fopen("lca.in", "r");
outfile = fopen("lca.out", "w");
fscanf(infile, "%d %d", &n, &m);
tree = malloc((n+1) * sizeof(struct node*));
for (i = 0; i <= n; i++)
tree[i] = NULL;
euler = malloc((2 * n - 1) * sizeof(int));
level = malloc((2 * n - 1) * sizeof(int));
index = malloc((n+1) * sizeof(int));
for (i = 1; i < n; i++) {
int x;
fscanf(infile, "%d", &x);
list_add_front(&tree[x], i+1);
}
dfs(tree, 1, euler, level, index, 0, &count);
st_create(&segtree, level, 2 * n -1);
for (i = 0; i < m; i++) {
int q1, q2;
fscanf(infile, "%d %d", &q1, &q2);
if (index[q1] > index[q2]) {
int aux = q1;
q1 = q2;
q2 = aux;
}
int x = get_min(segtree, level, 1, 0, 2 * n - 2, index[q1], index[q2]);
fprintf(outfile, "%d\n", euler[x]);
}
fclose(infile);
fclose(outfile);
return 0;
}