Cod sursa(job #3040157)

Utilizator rastervcrastervc rastervc Data 29 martie 2023 13:40:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.04 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

using Graph = vector<vector<int>>;
constexpr int INF = 2e9;

class LCA {
    vector<int> euler, first, level;
    vector<bool> visited;
    vector<vector<int>> rmq;
    int N, M;

    inline void dfs(const Graph& G, int node, int lvl) {
        visited[node] = true;
        level[node] = lvl;
        first[node] = euler.size();
        euler.push_back(node);
        for (const int adj : G[node])
            if (!visited[adj]) {
                dfs(G, adj, lvl + 1);
                euler.push_back(node);
            }
    }

public:
    LCA(const Graph& G, int root) noexcept {
        N = G.size();
        first.resize(N);
        level.resize(N);
        visited.resize(N, false);
        euler.reserve(2 * N);

        dfs(G, root, 0);

        M = euler.size();
        rmq.resize((int)log2(M) + 1);

        for (int i = 0; i < M; ++i)
            rmq[0].push_back(euler[i]);
        
        for (int i = 1; i < rmq.size(); ++i)
            for (int j = 0; j + (1 << i) - 1 < M; ++j) {
                const int l = rmq[i - 1][j];
                const int r = rmq[i - 1][j + (1 << (i - 1))];
                rmq[i].push_back(level[l] < level[r] ? l : r);
            }
    }

    inline int query(int node1, int node2) const {
        int l = first[node1], r = first[node2];
        if (l > r) swap(l, r);
        const int lg_len = (int)log2(r - l + 1);
        const int ans1 = rmq[lg_len][l], ans2 = rmq[lg_len][r - (1 << lg_len) + 1];
        return level[ans1] < level[ans2] ? ans1 : ans2;
    }
};

ifstream fin("lca.in");
ofstream fout("lca.out");

int main() {
    int N, M, node1, node2;
    fin >> N >> M;
    Graph G(N);
    for (int i = 1; i < N; ++i) {
        fin >> node1;
        G[node1 - 1].push_back(i);
    }

    LCA lca(G, 0);

    for (int i = 0; i < M; ++i) {
        fin >> node1 >> node2;
        --node1, --node2;
        fout << lca.query(node1, node2) + 1 << '\n';
    }

    return 0;
}