Cod sursa(job #2458906)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 21 septembrie 2019 19:53:07
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.52 kb
#include <bits/stdc++.h>

//#define input   std::cin
//#define output  std::cout
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:
    LCACalculator(std::vector <std::vector <int>> &graph) {
        if (_log2[2] == 0) precompute();
        this->graph = &graph;
        depth.resize(2*graph.size(), 0);
        first.resize(graph.size(), 0);
        DFS();
        buildRMQ();
    }
    ~LCACalculator() {
        depth.clear();
        first.clear();
    }

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

private:
    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);
    }   std::vector <std::vector <int>> *graph;
    std::vector <int> depth;
    std::vector <int> first;
    std::vector <int> euler;

    std::vector <int> RMQ[20];
    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)
                RMQ[i][j] = ((depth[RMQ[i-1][j]] < depth[RMQ[i-1][j + (1<<(i-1))]]) ? RMQ[i-1][j] : RMQ[i-1][j + (1<<(i-1))]);
    }
};

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

#define num int

inline void addEdge(std::vector <std::vector <int>> &graph, int x, int y) {
    graph[x].push_back(y);
    graph[y].push_back(x);
}

int N;
std::vector <std::vector <int>> ADC;
LCACalculator *calc;

int main()
{
    int N, Q;
    input >> N >> Q;
    ADC.resize(N);
    for (int i=1, x; i<N; ++i) {
        input >> x;
        addEdge(ADC, i, x-1);
    }   calc = new LCACalculator(ADC);

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

    return 0;
}