Cod sursa(job #2787800)

Utilizator preda.andreiPreda Andrei preda.andrei Data 24 octombrie 2021 01:25:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.11 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) {
    tree[node].time = euler.size();
    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);
    }
}

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 = 0; i < (int)euler.size(); i += 1) {
        dp[i].push_back(euler[i]);

        for (int k = 0; i - (1 << k) >= 0; k += 1) {
            if (k >= (int)dp[i - (1 << k)].size()) {
                break;
            }
            auto lnode = dp[i - (1 << k)][k];
            auto rnode = dp[i][k];

            if (tree[lnode].depth < tree[rnode].depth) {
                dp[i].push_back(lnode);
            } else {
                dp[i].push_back(rnode);
            }
        }
    }
    return dp;
}

int Log2(int n) {
    static vector<int> memo{0, 0};
    while ((int)memo.size() <= n) {
        int x = memo.size();
        memo.push_back(memo[x / 2] + 1);
    }
    return memo[n];
}

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 = Log2(r - l + 1);
    auto lnode = dp[l + (1 << pow) - 1][pow];
    auto rnode = dp[r][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);
    }

    Log2(nodes);

    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;
}