Cod sursa(job #2787729)

Utilizator preda.andreiPreda Andrei preda.andrei Data 23 octombrie 2021 22:19:53
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.77 kb
#include <fstream>
#include <vector>

#include <iostream>

using namespace std;

struct Node {
    vector<int> edges;
    vector<int> pred;
    int time = -1;
};

using Tree = vector<Node>;

void Dfs(Tree& tree, int node, int parent =-1) {
    if (parent != -1) {
        tree[node].pred.push_back(parent);
        auto ancestor = parent;

        for (size_t i = 0; i < tree[ancestor].pred.size(); i += 1) {
            auto older = tree[ancestor].pred[i];
            tree[node].pred.push_back(older);
            ancestor = older;
        }
    }

    for (const auto& child : tree[node].edges) {
        Dfs(tree, child, node);
    }

    static auto time = 0;
    tree[node].time = (time += 1);
}

void Precalc(Tree& tree) {
    Dfs(tree, 0);
}

int Lca(const Tree& tree, int a, int b) {
    if (tree[a].time < tree[b].time) {
        swap(a, b);
    }
    if (a == 0) {
        return a;
    }

    while (tree[b].time < tree[a].time) {
        int ind = -1;
        for (int pow = 1 << 25; pow > 0; pow >>= 1) {
            auto next = ind + pow;
            if (next >= (int)tree[b].pred.size()) {
                continue;
            }

            auto anc = tree[b].pred[next];
            if (tree[anc].time < tree[a].time) {
                ind = next;
            }
        }
        b = tree[b].pred[ind + 1];
    }
    return b;
}

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

    Precalc(tree);

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