Pagini recente » Cod sursa (job #1565396) | Cod sursa (job #1096945) | Monitorul de evaluare | Cod sursa (job #453973) | Cod sursa (job #3041282)
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
ifstream cin("lca.in");
ofstream cout("lca.out");
const int NMAX = 4e5;
int n, m;
int K;
int euler[NMAX + 5], lvl[NMAX + 5], first[NMAX + 5], rmq[NMAX + 5][20];
vector<vector<int>> edges;
void dfs(int node, int depth)
{
euler[++K] = node;
lvl[K] = depth;
first[node] = K;
for (auto it : edges[node])
{
dfs(it, depth + 1);
euler[++K] = node;
lvl[K] = depth;
}
}
void preprocess()
{
for (int i = 1; i <= K; i++)
rmq[i][0] = i;
for (int j = 1; (1 << j) <= K; j++)
{
for (int i = 1; i + (1 << j) - 1 <= K; i++)
{
if (lvl[rmq[i][j - 1]] > lvl[rmq[i + (1 << (j - 1))][j - 1]])
rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1];
else
rmq[i][j] = rmq[i][j - 1];
}
}
}
int query(int l, int r)
{
int aux = log2(r - l + 1);
if (lvl[rmq[l][aux]] < lvl[rmq[r - (1 << aux) + 1][aux]])
return rmq[l][aux];
else
return rmq[r - (1 << aux) + 1][aux];
}
int lca(int a, int b)
{
int st = first[a], dr = first[b];
if (st > dr)
swap(st, dr);
int aux = query(st, dr);
return euler[aux];
}
int main()
{
cin >> n >> m;
edges.resize(n + 1);
for (int i = 2; i <= n; i++)
{
int x;
cin >> x;
edges[x].push_back(i);
}
dfs(1, 0);
// for (int i = 1; i <= K; i++)
// {
// cout << euler[i] << " \n"[i == K];
// }
// for (int i = 1; i <= K; i++)
// {
// cout << lvl[i] << " \n"[i == K];
// }
preprocess();
for (int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
cout << lca(a, b) << '\n';
}
return 0;
}