Cod sursa(job #2787790)

Utilizator preda.andreiPreda Andrei preda.andrei Data 24 octombrie 2021 00:31:24
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.06 kb
#include <fstream>
#include <vector>

using namespace std;

struct Node {
    vector<int> edges;
    int depth = 0;
    int time = 0;
};

using Tree = vector<Node>;

void Euler(Tree& tree, int node, vector<int>& euler) {
    euler.push_back(node);

    for (const auto& next : tree[node].edges) {
        tree[next].depth = tree[node].depth + 1;
        Euler(tree, next, euler);
        euler.push_back(node);
    }

    tree[node].time = euler.size();
    euler.push_back(node);
}

vector<vector<int>> Precalc(Tree& tree) {
    vector<int> euler;
    tree[0].depth = 0;
    Euler(tree, 0, euler);

    vector<vector<int>> dp(euler.size());
    for (int i = euler.size() - 1; i >= 0; i -= 1) {
        int right = i + 1;

        dp[i].push_back(euler[i]);
        for (int k = 0; right < (int)dp.size() && k < (int)dp[right].size(); k += 1) {
            auto lnode = dp[i][k];
            auto rnode = dp[right][k];

            if (tree[lnode].depth < tree[rnode].depth) {
                dp[i].push_back(lnode);
            } else {
                dp[i].push_back(rnode);
            }
            right = i + (1 << (k + 1));
        }
    }
    return dp;
}

int Lca(const Tree& tree, const vector<vector<int>>& dp, int a, int b) {
    auto l = min(tree[a].time, tree[b].time);
    auto r = max(tree[a].time, tree[b].time);

    int pow = 0;
    while ((1 << (pow + 1)) <= (r - l + 1)) {
        pow += 1;
    }

    if ((1 << pow) == (r - l + 1)) {
        return dp[l][pow];
    }

    auto lnode = dp[l][pow];
    auto rnode = dp[r - (1 << pow) + 1][pow];

    return tree[lnode].depth < tree[rnode].depth ? lnode : rnode;
}

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 += 1) {
        int parent;
        fin >> parent;
        tree[parent - 1].edges.push_back(i);
    }

    auto dp = Precalc(tree);

    for (int i = 0; i < queries; i += 1) {
        int a, b;
        fin >> a >> b;
        fout << Lca(tree, dp, a - 1, b - 1) + 1 << "\n";
    }
    return 0;
}