Cod sursa(job #2749929)

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

#define MAXN    100005
#define LOG2    20


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 {
        LCAData(int p=0) : parent(p) {}
        int parent;
    };

    bool cmp(const LCAData &one, const LCAData &other) const {
        return depth[one.parent] < depth[other.parent];
    }

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

    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.parent], x};
        return {euler[y.parent], x};
    }

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(), LCAData());
        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};


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

int32_t main()
{
    int N, M;
    std::vector <std::vector <int>> graph;
    input >> N >> M;
    graph.resize(N);
    for (int i=1, u; i<N; ++i)
        input >> u, graph[u-1].push_back(i), graph[i].push_back(u-1);
    LCACalculator calc(graph);
    for (int i=1, x, y; i<=M; ++i)
        input >> x >> y, output << calc.query(x-1, y-1).first + 1 << '\n';

    return 0;
}