Pagini recente » Cod sursa (job #189397) | Rating Farcas Egidiu (Egidiu) | Cod sursa (job #2112035) | Arhiva de probleme | Cod sursa (job #2150178)
#include <fstream>
#include <vector>
using namespace std;
struct Node
{
int level;
int position;
vector<int> sons;
};
using Tree = vector<Node>;
using RmqMat = vector<vector<int>>;
void Euler(Tree &t, int node, vector<int> &euler, int level = 0)
{
t[node].level = level;
t[node].position = euler.size();
euler.push_back(node);
for (const auto &son : t[node].sons) {
Euler(t, son, euler, level + 1);
euler.push_back(node);
}
}
RmqMat PrecalcLca(const Tree &t, const vector<int> &euler)
{
RmqMat rmq(euler.size());
for (size_t i = 0; i < euler.size(); ++i) {
rmq[i].push_back(euler[i]);
for (int power = 0; (int)i - 2 * (1 << power) >= -1; ++power) {
auto ind = (int)i - (1 << power);
auto left = rmq[ind][power];
auto right = rmq[i][power];
auto res = (t[left].level < t[right].level ? left : right);
rmq[i].push_back(res);
}
}
return rmq;
}
int FindSmallerPower(int max_num)
{
int power = 0;
while ((1 << (power + 1)) <= max_num) {
power += 1;
}
return power;
}
int FindRmq(const Tree &t, const RmqMat &rmq, int left, int right)
{
auto power = FindSmallerPower(right - left + 1);
auto a = rmq[left + (1 << power) - 1][power];
auto b = rmq[right][power];
return (t[a].level < t[b].level ? a : b);
}
int FindLca(const Tree &t, const RmqMat &rmq, int a, int b)
{
auto left = t[a].position;
auto right = t[b].position;
if (left > right) {
swap(left, right);
}
return FindRmq(t, rmq, left, right);
}
int main()
{
ifstream fin("lca.in");
ofstream fout("lca.out");
int nodes, queries;
fin >> nodes >> queries;
Tree tree(nodes);
for (int i = 1; i < nodes; ++i) {
int father;
fin >> father;
tree[father - 1].sons.push_back(i);
}
vector<int> euler;
Euler(tree, 0, euler);
auto lca = PrecalcLca(tree, euler);
for (int i = 0; i < queries; ++i) {
int a, b;
fin >> a >> b;
auto res = FindLca(tree, lca, a - 1, b - 1);
fout << res + 1 << "\n";
}
return 0;
}