This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub suisen-cp/cp-library-cpp
#define PROBLEM "https://judge.yosupo.jp/problem/lca" #include <iostream> #include "library/tree/level_ancestor.hpp" using suisen::LevelAncestor; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, q; std::cin >> n >> q; std::vector<std::vector<int>> g(n); for (int i = 1; i < n; ++i) { int p; std::cin >> p; g[p].push_back(i); g[i].push_back(p); } LevelAncestor la(g); auto lca = [&](int u, int v) -> int { int du = la.get_depth(u); int dv = la.get_depth(v); if (du < dv) { std::swap(u, v); std::swap(du, dv); } int l = -1, r = dv; while (r - l > 1) { int k = (l + r) >> 1; (la(u, k + (du - dv)) == la(v, k) ? r : l) = k; } return la(v, r); }; for (int query_id = 0; query_id < q; ++query_id) { int u, v; std::cin >> u >> v; std::cout << lca(u, v) << '\n'; } return 0; }
#line 1 "test/src/tree/level_ancestor/lowest_common_ancestor.test.cpp" #define PROBLEM "https://judge.yosupo.jp/problem/lca" #include <iostream> #line 1 "library/tree/level_ancestor.hpp" #include <algorithm> #include <vector> namespace suisen { struct LevelAncestor { LevelAncestor() = default; LevelAncestor(const std::vector<std::vector<int>>& g, const int root = 0) : _n(g.size()), _visit_time(_n), _visit_time_inv(_n), _depth(_n), _count(_n + 1), _bucket(_n) { build(g, root); } int query(const int u, const int k) const { if (k < 0 or k > _depth[u]) return -1; const int d = _depth[u] - k; const auto it_l = _bucket.begin() + _count[d], it_r = _bucket.begin() + _count[d + 1]; const int visit_time_u = _visit_time[u]; const int visit_time_v = *std::prev(std::upper_bound(it_l, it_r, visit_time_u)); return _visit_time_inv[visit_time_v]; } int operator()(const int u, const int k) const { return query(u, k); } int get_visit_time(const int u) const { return _visit_time[u]; } int get_visit_time_inv(const int t) const { return _visit_time_inv[t]; } int get_kth_visited(const int k) const { return _visit_time_inv[k]; } int get_depth(const int u) const { return _depth[u]; } private: int _n; std::vector<int> _visit_time; // vertex -> time std::vector<int> _visit_time_inv; // time -> vertex std::vector<int> _depth; // vertex -> depth std::vector<int> _count; // the leftmost index of the i'th block in the `_bucket` std::vector<int> _bucket; // [|dep=0|dep=1|dep=2|...|dep=n-1|]. Each block contains the visited times in ascending order. void build(const std::vector<std::vector<int>>& g, const int root) { int time = 0; auto dfs = [&](auto dfs, int u, int p) -> void { _visit_time[u] = time; _visit_time_inv[time] = u; ++time; ++_count[_depth[u] + 1]; for (int v : g[u]) if (v != p) { _depth[v] = _depth[u] + 1; dfs(dfs, v, u); } }; dfs(dfs, root, -1); for (int i = 0; i < _n; ++i) _count[i + 1] += _count[i]; auto index = _count; for (int v : _visit_time_inv) _bucket[index[_depth[v]]++] = _visit_time[v]; } }; } // namespace suisen #line 6 "test/src/tree/level_ancestor/lowest_common_ancestor.test.cpp" using suisen::LevelAncestor; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, q; std::cin >> n >> q; std::vector<std::vector<int>> g(n); for (int i = 1; i < n; ++i) { int p; std::cin >> p; g[p].push_back(i); g[i].push_back(p); } LevelAncestor la(g); auto lca = [&](int u, int v) -> int { int du = la.get_depth(u); int dv = la.get_depth(v); if (du < dv) { std::swap(u, v); std::swap(du, dv); } int l = -1, r = dv; while (r - l > 1) { int k = (l + r) >> 1; (la(u, k + (du - dv)) == la(v, k) ? r : l) = k; } return la(v, r); }; for (int query_id = 0; query_id < q; ++query_id) { int u, v; std::cin >> u >> v; std::cout << lca(u, v) << '\n'; } return 0; }