Cod sursa(job #2749931)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 9 mai 2021 01:54:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.47 kb
#include <bits/stdc++.h>

std::ifstream input ("lca.in");
std::ofstream output("lca.out");

#define MAXN    2000005

class LCACalculator {
private:
    static int _log2[MAXN];
    static void precompute() {
        for (int i=2; i<MAXN; ++i)
            _log2[i] = _log2[i>>1] + 1;
    }

public:
    struct LCAData { int v; };

    LCACalculator(const std::vector <std::vector <int>> &graph) : graph(graph) {
        if (_log2[2] == 0) precompute();
        depth.resize(2*graph.size(), 0);
        first.resize(graph.size(), 0);
        DFS();
        buildRMQ();
    }

    bool cmp(const LCAData &x, const LCAData &y) const {
        return depth[x.v] < depth[y.v];
    }

    std::pair <int, LCAData> query(int v, int w) {
        v = first[v];
        w = first[w];
        if (w < v) std::swap(v, w);
        int len = _log2[w-v + 1];
        auto x = RMQ[len][v], y = RMQ[len][w - (1<<len)+1];
        if (cmp(x, y)) return { euler[x.v], x };
        return { euler[y.v], y };
    }

private:
    std::vector <std::vector <int>> graph;
    std::vector <int> depth;
    std::vector <int> first;
    std::vector <int> euler;
    std::vector <LCAData> RMQ[20];

    void DFS(int vertex = 0, int parent = 0, int lvl = 1) {
        first[vertex] = euler.size();
        depth[euler.size()] = lvl;
        euler.push_back(vertex);
        for (auto it:graph[vertex]) if (it != parent)
            DFS(it, vertex, lvl+1),
            depth[euler.size()] = lvl,
            euler.push_back(vertex);
    }

    void buildRMQ() {
        for (int i=0, size; (1<<i)<=euler.size(); ++i)
            RMQ[i].resize(euler.size(), { 0 });
        for (int i=0; i<euler.size(); ++i)
            RMQ[0][i] = { i };
        for (int i=1; (1<<i)<=euler.size(); ++i)
            for (int j=0; j+(1<<i)<=euler.size(); ++j)
                if (cmp(RMQ[i-1][j], RMQ[i-1][j + (1<<(i-1))]))
                    RMQ[i][j] = RMQ[i-1][j];
                else RMQ[i][j] = RMQ[i-1][j + (1<<(i-1))];
    }
};

int LCACalculator::_log2[MAXN] = {0};


int main()
{
    std::vector <std::vector <int>> graph;
    int N, Q;
    input >> N >> Q;
    graph.resize(N);
    for (int i=1, x; i<N; ++i) {
        input >> x;
        graph[i].push_back(x-1), graph[x-1].push_back(i);
    }

    auto calc = LCACalculator(graph);

    int x, y;
    while (Q--) {
        input >> x >> y;
        output << calc.query(x-1, y-1).first + 1 << '\n';
    }

    return 0;
}