This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub HyunjaeLee/Algorithms
#define PROBLEM "https://judge.yosupo.jp/problem/lca" #include "heavy_light_decomposition/heavy_light_decomposition.hpp" #include <bits/stdc++.h> int main() { std::cin.tie(0)->sync_with_stdio(0); int N, Q; std::cin >> N >> Q; std::vector<std::vector<int>> adj(N); for (auto i = 1; i < N; ++i) { int p; std::cin >> p; adj[p].push_back(i); } heavy_light_decomposition hld(adj, 0); while (Q--) { int u, v; std::cin >> u >> v; std::cout << hld.lca(u, v) << '\n'; } }
#line 1 "test/heavy_light_decomposition_lca.test.cpp" #define PROBLEM "https://judge.yosupo.jp/problem/lca" #line 1 "heavy_light_decomposition/heavy_light_decomposition.hpp" #include <algorithm> #include <cassert> #include <type_traits> #include <vector> struct heavy_light_decomposition { heavy_light_decomposition(const std::vector<std::vector<int>> &graph, int root) : n_(static_cast<int>(graph.size())), timer_(0), graph_(graph), size_(n_, 1), depth_(n_), parent_(n_, -1), top_(n_), in_(n_), out_(n_) { assert(0 <= root && root < n_); top_[root] = root; dfs_size(root); dfs_hld(root); } template <typename Function> void access_node(int u, Function f) { assert(0 <= u && u < n_); f(in_[u]); } template <typename Function> std::enable_if_t< std::is_same_v<std::invoke_result_t<Function, int, int>, void>, void> access_path(int u, int v, bool include_lca, Function f) const { assert(0 <= u && u < n_ && 0 <= v && v < n_); while (top_[u] != top_[v]) { if (depth_[top_[u]] < depth_[top_[v]]) { std::swap(u, v); } f(in_[top_[u]], in_[u] + 1); u = parent_[top_[u]]; } if (depth_[u] > depth_[v]) { std::swap(u, v); } if (include_lca) { f(in_[u], in_[v] + 1); } else { f(in_[u] + 1, in_[v] + 1); } } template <typename Function> std::enable_if_t< std::is_same_v<std::invoke_result_t<Function, int, int, bool>, void>, void> access_path(int u, int v, bool include_lca, Function f) const { assert(0 <= u && u < n_ && 0 <= v && v < n_); bool u_to_lca = true; while (top_[u] != top_[v]) { if (depth_[top_[u]] < depth_[top_[v]]) { std::swap(u, v); u_to_lca = !u_to_lca; } f(in_[top_[u]], in_[u] + 1, u_to_lca); u = parent_[top_[u]]; } if (depth_[u] > depth_[v]) { std::swap(u, v); } else { u_to_lca = !u_to_lca; } if (include_lca) { f(in_[u], in_[v] + 1, u_to_lca); } else { f(in_[u] + 1, in_[v] + 1, u_to_lca); } } template <typename Function> void access_subtree(int u, bool include_root, Function f) const { assert(0 <= u && u < n_); if (include_root) { f(in_[u], out_[u]); } else { f(in_[u] + 1, out_[u]); } } int lca(int u, int v) const { assert(0 <= u && u < n_ && 0 <= v && v < n_); while (top_[u] != top_[v]) { if (depth_[top_[u]] < depth_[top_[v]]) { std::swap(u, v); } u = parent_[top_[u]]; } if (depth_[u] > depth_[v]) { std::swap(u, v); } return u; } private: void dfs_size(int u) { auto it = std::find(graph_[u].begin(), graph_[u].end(), parent_[u]); if (it != graph_[u].end()) { graph_[u].erase(it); } for (auto &v : graph_[u]) { depth_[v] = depth_[u] + 1; parent_[v] = u; dfs_size(v); size_[u] += size_[v]; if (size_[v] > size_[graph_[u][0]]) { std::swap(v, graph_[u][0]); } } } void dfs_hld(int u) { in_[u] = timer_++; for (auto v : graph_[u]) { top_[v] = (v == graph_[u][0] ? top_[u] : v); dfs_hld(v); } out_[u] = timer_; } int n_, timer_; std::vector<std::vector<int>> graph_; std::vector<int> size_, depth_, parent_, top_, in_, out_; }; #line 4 "test/heavy_light_decomposition_lca.test.cpp" #include <bits/stdc++.h> int main() { std::cin.tie(0)->sync_with_stdio(0); int N, Q; std::cin >> N >> Q; std::vector<std::vector<int>> adj(N); for (auto i = 1; i < N; ++i) { int p; std::cin >> p; adj[p].push_back(i); } heavy_light_decomposition hld(adj, 0); while (Q--) { int u, v; std::cin >> u >> v; std::cout << hld.lca(u, v) << '\n'; } }