Cod sursa(job #3039901)

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

using namespace std;

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

class LCA {
    vector<int> euler, first, level, tree;
    vector<bool> visited;
    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);
            }
    }

    inline void build(int node, int l, int r) {
        if (l == r) tree[node] = euler[l];
        else {
            const int mid = (l + r) >> 1;
            build(node << 1, l, mid);
            build((node << 1) | 1, mid + 1, r);
            const int son1 = tree[node << 1];
            const int son2 = tree[(node << 1) | 1];
            tree[node] = level[son1] < level[son2] ? son1 : son2;
        }
    }

    inline int query(int node, int l, int r, int a, int b) const {
        if (a <= l && r <= b) return tree[node];
        else {
            const int mid = (l + r) >> 1;
            int ans1 = INF, ans2 = INF;
            if (a <= mid) ans1 = query(node << 1, l, mid, a, b);
            if (mid < b) ans2 = query((node << 1) | 1, mid + 1, r, a, b);
            if (ans1 == INF) return ans2;
            if (ans2 == INF) return ans1;
            return level[ans1] < level[ans2] ? ans1 : ans2;
        }
    }

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();
        tree.resize(4 * M);
        build(1, 0, M - 1);
    }

    inline int query(int node1, int node2) const {
        int l = first[node1], r = first[node2];
        if (l > r) swap(l, r);
        return query(1, 0, M - 1, l, r);
    }
};

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;
}