Cod sursa(job #2150178)

Utilizator preda.andreiPreda Andrei preda.andrei Data 3 martie 2018 12:28:31
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.23 kb
#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;
}