#include <iostream>
#include <fstream>
#include <vector>
void mySwap (int &a, int &b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int findParent(int &node, int *parent) {
if (node != parent[node])
parent[node] = findParent(parent[node], parent);
return parent[node];
}
void makeUnion (int &node1, int &node2, int *parent, int *rank) {
int root1 = findParent(node1, parent);
int root2 = findParent(node2, parent);
if (root1 != root2) {
if (rank[root1] < rank[root2])
mySwap(root1, root2);
parent[root2] = root1;
if (rank[root1] == rank[root2])
rank[root1]++;
}
}
void recursiveDfs(int &node, std::vector<std::vector<int>> &graph,
std::vector< std::vector< std::pair<int, int> > >& queries, bool *visited,
int *ancestor, int *parent, int *rank, std::vector<int> &answer) {
parent[node] = node;
ancestor[node] = node;
rank[node] = 1;
visited[node] = 1;
for (int i = 0; i < graph[node].size(); ++i) {
if (!visited[graph[node][i]]) {
recursiveDfs(graph[node][i], graph, queries, visited,
ancestor, parent, rank, answer);
makeUnion(node, graph[node][i], parent, rank);
ancestor[findParent(node, parent)] = node;
}
}
for (int i = 0; i < queries[node].size(); ++i) {
if (visited[queries[node][i].first] == 1)
answer[queries[node][i].second] =
ancestor[findParent(queries[node][i].first, parent)];
}
}
std::vector<int> lca(std::vector<std::vector<int>> &graph,
std::vector< std::pair<int, int> > &queries) {
bool *visited;
int node = 1, *ancestor, *rank, *parent;
std::vector<int> answer(queries.size(), 0);
std::vector< std::vector< std::pair<int, int> > > eachNodeQuery(graph.size());
for (int i = 0; i < queries.size(); ++i) {
eachNodeQuery[queries[i].first].push_back({queries[i].second, i});
eachNodeQuery[queries[i].second].push_back({queries[i].first, i});
}
visited = new bool[graph.size()] {0};
ancestor = new int[graph.size()] {0};
parent = new int[graph.size()] {0};
rank = new int[graph.size()] {1};
recursiveDfs(node, graph, eachNodeQuery, visited, ancestor, parent, rank, answer);
delete [] visited;
delete [] ancestor;
delete [] rank;
delete [] parent;
return answer;
}
int main () {
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
int n, m, node1, node2;
std::vector< std::vector<int> > graph;
std::vector< std::pair<int, int> > queries;
fin >> n >> m; // number of nodes and queries
graph.resize(n + 1);
for (int i = 2; i <= n; ++i) {
fin >> node1;
graph[node1].push_back(i);
graph[i].push_back(node1);
// fin >> node1 >> node2;
// graph[node1].push_back(node2);
// graph[node2].push_back(node1);
}
for (int i = 0; i < m; ++i) {
fin >> node1 >> node2;
queries.push_back({node1, node2});
}
std::vector<int> ans = lca(graph, queries);
for (int i = 0; i < ans.size(); ++i) {
fout << ans[i] << "\n";
}
return 0;
}