#include <iostream>
#include <fstream>
#include <vector>
#define INF 0x3f3f3f3f
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
void mySwap (int &a, int &b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
void recursiveDfs (int &node, int &level, std::vector<int> &eulerRep,
std::vector<int> &levelEvidence, int *firstOccourance,
std::vector<std::vector<int>> &graph, int &fromNode) {
eulerRep.push_back(node);
levelEvidence.push_back(level);
firstOccourance[node] = eulerRep.size() - 1;
for (int i = 0; i < graph[node].size(); ++i) {
if (graph[node][i] == fromNode)
continue;
int nextLevel = level + 1;
recursiveDfs(graph[node][i], nextLevel, eulerRep, levelEvidence,
firstOccourance, graph, node);
eulerRep.push_back(node);
levelEvidence.push_back(level);
}
}
void makeSegmentTree(int &node, int &left, int &right,
int *segmentTree, std::vector<int> &levelEvidence) {
if (left == right) {
segmentTree[node] = left;
// std::cout << node;
// std::cout << "\n";
// return;
} else {
int mijl = ((left + right) >> 1);
int nodeLeft = (node << 1);
int nodeRight = ((node << 1) + 1);
// std::cout << node << " -> " << nodeLeft << " si " << nodeRight;
// std::cout << "\n";
makeSegmentTree(nodeLeft, left, mijl, segmentTree, levelEvidence);
++mijl;
makeSegmentTree(nodeRight, mijl, right, segmentTree, levelEvidence);
if (levelEvidence[segmentTree[nodeLeft]] <=
levelEvidence[segmentTree[nodeRight]]) {
segmentTree[node] = segmentTree[nodeLeft];
} else {
segmentTree[node] = segmentTree[nodeRight];
}
}
}
void querryLca(int &node, int &left, int &right,
int *segmentTree, std::vector<int> &levelEvidence, std::vector<int> &eulerRep,
int &sol, int &solH, int &nodeLeft, int &nodeRight) {
if (nodeLeft <= left && right <= nodeRight) {
// 123523
if (levelEvidence[segmentTree[node]] < solH) {
// fout << node << "\n";
// 46292
sol = eulerRep[segmentTree[node]];
solH = levelEvidence[segmentTree[node]];
}
// return sol;
} else {
int mijl = ((left + right) >> 1);
int nodeL = (node << 1);
int nodeR = ((node << 1) + 1);
if (nodeLeft <= mijl)
querryLca(nodeL, left, mijl, segmentTree, levelEvidence, eulerRep,
sol, solH, nodeLeft, nodeRight);
++mijl;
if (mijl <= nodeRight)
querryLca(nodeR, mijl, right, segmentTree, levelEvidence, eulerRep,
sol, solH, nodeLeft, nodeRight);
}
}
std::vector<int> lca(std::vector<std::vector<int>> &graph,
std::vector< std::pair<int, int> > &queries) {
std::vector<int> eulerRep, levelEvidence, ans;
eulerRep.push_back(0);
levelEvidence.push_back(0);
int *firstOccourance;
int node = 1, level = 0, **rmq, *lg;
int left = 1;
firstOccourance = new int [graph.size() + 2];
recursiveDfs(node, level, eulerRep, levelEvidence, firstOccourance, graph, level);
int *segmentTree;
segmentTree = new int [levelEvidence.size() * 4] {0};
int right = levelEvidence.size() - 1;
makeSegmentTree(node, left, right, segmentTree, levelEvidence);
// segmentTree[1] = 1;
for (int i = 0; i < queries.size(); ++i) {
int nodeL = firstOccourance[queries[i].first];
int nodeR = firstOccourance[queries[i].second];
if (nodeL > nodeR)
mySwap(nodeL, nodeR);
int sol = INF;
int solH = INF;
querryLca(node, left, right, segmentTree, levelEvidence, eulerRep,
sol, solH, nodeL, nodeR);
ans.push_back(sol);
}
// for (int i = 0; i < eulerRep.size() * 3; ++i) {
// fout << segmentTree[i] << "\n";
// }
// std::cout << "peste\n";
// std::cout << "\n";
// for (int i = 0; i < eulerRep.size(); ++i) {
// std::cout << i << " -> " << levelEvidence[i] << " \n";
// }
// std::cout << "\n";
// for (int i = 0; i < eulerRep.size(); ++i) {
// std::cout << i << " -> " << eulerRep[i] << " \n";
// }
// std::cout << "\n";
delete [] firstOccourance;
delete [] segmentTree;
return ans;
}
int main () {
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;
}