Pagini recente » Cod sursa (job #724503) | Cod sursa (job #976616) | Cod sursa (job #1505029) | Cod sursa (job #1542484) | Cod sursa (job #2406649)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <limits>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int const inf = numeric_limits<int>::max();
vector<int> height, euler, first, segtree;
vector<bool> visited;
vector<vector<int>> adjList;
int query(int i, int l, int r, int ql, int qr)
{
if (qr < l || r < ql)
{
return -1;
}
if (ql <= l && r <= qr)
{
return segtree[i];
}
int mid = (l + r) / 2;
int L = query(i * 2, l, mid, ql, qr);
int R = query(i * 2 + 1, mid + 1, r, ql, qr);
if (L == -1)
return R;
if (R == -1)
return L;
if (height[L] <= height[R])
return L;
else
return R;
}
void build(int i, int l, int r)
{
if (l == r)
{
segtree[i] = euler[l];
return;
}
int mid = (l + r) / 2;
build(i * 2, l, mid);
build(i * 2 + 1, mid + 1, r);
int left = segtree[i * 2];
int right = segtree[i * 2 + 1];
if (height[left] <= height[right])
segtree[i] = left;
else
segtree[i] = right;
}
void dfs(int u, int h = 0)
{
visited[u] = true;
first[u] = euler.size();
height[u] = h;
euler.push_back(u);
for (auto to : adjList[u])
{
if (visited[to] == false)
{
dfs(to, h + 1);
euler.push_back(u);
}
}
}
int lca(int u, int v)
{
int left = first[u], right = first[v];
if (left > right)
swap(left, right);
return query(1, 0, euler.size() - 1, left, right);
}
int main()
{
int n, m;
fin >> n >> m;
adjList.resize(n + 1);
for (int i = 2; i <= n; i++)
{
int x;
fin >> x;
adjList[x].push_back(i);
}
visited.assign(n + 1, false);
euler.reserve(2 * n + 2);
height.resize(n + 1);
first.resize(n + 1);
dfs(1, 1);
int esz = euler.size();
segtree.resize(esz * 4);
build(1, 0, euler.size() - 1);
for (auto a : first)
cout << a << " ";
for (int i = 0; i < m; i++)
{
int x, y;
fin >> x >> y;
fout << lca(x, y) << "\n";
}
return 0;
}