Cod sursa(job #2051985)

Utilizator retrogradLucian Bicsi retrograd Data 29 octombrie 2017 20:05:37
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.06 kb
#include <bits/stdc++.h>

using namespace std;

template<typename T>
struct RMQ {
    int n;
    vector<vector<T>> mem;
    vector<int> log;

    void Build(vector<T> V) { 
        n = V.size();
        log.resize(n + 1);
        log[1] = 0;
        for (int i = 2; i <= n; ++i)
            log[i] = 1 + log[i / 2];

        mem.emplace_back(move(V));
        for (int it = 1; mem.back().size() > 1; ++it) {
            vector<T> nwmem; 
            int step = (1 << it), lim = mem.back().size();
            for (int i = 0, j = step / 2; j < lim; ++i, ++j) 
                nwmem.push_back(min(mem.back()[i], mem.back()[j]));
            mem.emplace_back(move(nwmem));
        } 
    }

    T Query(int a, int b) {
        int i = log[b - a];
        return min(mem[i][a], mem[i][b - (1 << i)]);
    }
};

struct LCA {
    vector<int> enter, depth;
    vector<vector<int>> G;
    vector<pair<int, int>> linear;
    RMQ<pair<int, int>> rmq;
    int timer = 0;

    LCA(int n) : enter(n, -1), depth(n), G(n), linear(2 * n) {}

    void dfs(int node, int dep) {
        linear[timer] = {dep, node};
        enter[node] = timer++;
        depth[node] = dep;

        for (auto vec : G[node])
            if (enter[vec] == -1) {
                dfs(vec, dep + 1);
                linear[timer++] = {dep, node};
            }
    }

    void AddEdge(int a, int b) {
        G[a].push_back(b);
        G[b].push_back(a);
    }

    void Build(int root) {
        dfs(root, 0);
        rmq.Build(linear);
    }

    int Query(int a, int b) {
        a = enter[a], b = enter[b];
        return rmq.Query(min(a, b), max(a, b) + 1).second;
    }
    int Distance(int a, int b) {
        return depth[a] + depth[b] - 2 * depth[Query(a, b)];
    }
};

int main() {
    ifstream cin("lca.in");
    ofstream cout("lca.out");

    int n, m; cin >> n >> m;
    LCA lca(n);

    for (int i = 1; i < n; ++i) {
        int par; cin >> par;
        lca.AddEdge(par - 1, i);
    } 
    lca.Build(0);
    while (m--) {
        int a, b; cin >> a >> b;
        cout << 1 + lca.Query(a - 1, b - 1) << '\n';
    }
    return 0;
}