icpc_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub ebi-fly13/icpc_library

:heavy_check_mark: test/tree/Lowest_Common_Ancestor.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/lca"

#include "../../template/template.hpp"
#include "../../tree/LowestCommonAncestor.hpp"

int main() {
    int n, q;
    std::cin >> n >> q;
    std::vector g(n, std::vector<int>());
    rep(i, 1, n) {
        int p;
        std::cin >> p;
        g[p].emplace_back(i);
        g[i].emplace_back(p);
    }
    lib::LowestCommonAncestor lca(g, 0);
    while (q--) {
        int u, v;
        std::cin >> u >> v;
        std::cout << lca.lca(u, v) << '\n';
    }
}
#line 1 "test/tree/Lowest_Common_Ancestor.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/lca"

#line 2 "template/template.hpp"

#include <bits/stdc++.h>

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <typename T> bool chmin(T &a, const T &b) {
    if (a <= b) return false;
    a = b;
    return true;
}
template <typename T> bool chmax(T &a, const T &b) {
    if (a >= b) return false;
    a = b;
    return true;
}

namespace lib {

using namespace std;

}  // namespace lib

// using namespace lib;
#line 2 "tree/LowestCommonAncestor.hpp"

#line 4 "tree/LowestCommonAncestor.hpp"

namespace lib {

struct LowestCommonAncestor {
    int n;
    std::vector<std::vector<int>> table;
    std::vector<int> depth;
    int log = 25;

    LowestCommonAncestor(const std::vector<std::vector<int>> &gh, int root = 0)
        : n(gh.size()) {
        table = std::vector(log, std::vector<int>(n, -1));
        depth.assign(n, 0);
        auto dfs = [&](auto &&self, int v) -> void {
            for (auto nv : gh[v]) {
                if (table[0][v] == nv) continue;
                table[0][nv] = v;
                depth[nv] = depth[v] + 1;
                self(self, nv);
            }
        };
        dfs(dfs, root);
        table[0][root] = root;
        rep(i, 0, log - 1) {
            rep(v, 0, n) {
                table[i + 1][v] = table[i][table[i][v]];
            }
        }
    }

    int la(int u, int k) const {
        if (depth[u] < k) return -1;
        rrep(i, 0, log) {
            if ((k >> i) & 1) {
                u = table[i][u];
            }
        }
        return u;
    }

    int lca(int u, int v) const {
        if (depth[u] < depth[v]) std::swap(u, v);
        u = la(u, depth[u] - depth[v]);
        if (u == v) return u;
        rrep(i, 0, log) {
            if (table[i][u] != table[i][v]) {
                u = table[i][u];
                v = table[i][v];
            }
        }
        return table[0][u];
    }

    int distance(int u, int v) const {
        int l = lca(u, v);
        return depth[u] + depth[v] - 2 * depth[l];
    };
};

}  // namespace lib
#line 5 "test/tree/Lowest_Common_Ancestor.test.cpp"

int main() {
    int n, q;
    std::cin >> n >> q;
    std::vector g(n, std::vector<int>());
    rep(i, 1, n) {
        int p;
        std::cin >> p;
        g[p].emplace_back(i);
        g[i].emplace_back(p);
    }
    lib::LowestCommonAncestor lca(g, 0);
    while (q--) {
        int u, v;
        std::cin >> u >> v;
        std::cout << lca.lca(u, v) << '\n';
    }
}
Back to top page