This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub dgcnz/cp-library
#include "cplib/data_structure/hld.hpp"
#ifndef CPLIB_HLD_HPP #define CPLIB_HLD_HPP #include <algorithm> #include <vector> namespace cplib { using namespace std; template <template <class S, S (*op)(S, S), S (*e)()> class segtree, class S, S (*op)(S, S), S (*e)()> struct HLD { using Tree = vector<vector<int>>; using SegmentTree = segtree<S, op, e>; Tree g; SegmentTree st; vector<int> parent, depth, heavy, head, pos; HLD(int n) : g(n), st(n), parent(n, 0), depth(n, 0), heavy(n, -1), head(n, 0), pos(n, 0) { } HLD(Tree _g) : HLD(_g.size()) { copy(begin(_g), end(_g), begin(g)); } void add_edge(int u, int v) { g[u].push_back(v), g[v].push_back(u); } void operator()(void) { int hld_pos = 0; dfs(0); decompose(0, 0, hld_pos); } int dfs(int u) { /* * Build depth and heavy array. * * u_sz: size of u's subtree * v_sz: size of v's subtree */ int u_sz = 1, mx_v_sz = 0, v_sz; for (int v : g[u]) { if (v != parent[u]) { parent[v] = u; depth[v] = depth[u] + 1; v_sz = dfs(v); u_sz += v_sz; if (v_sz > mx_v_sz) { mx_v_sz = v_sz; heavy[u] = v; } } } return u_sz; } // u: node, h: head of node void decompose(int u, int h, int &hld_pos) { /* * Decompose tree * * u: current node * h: head of node */ head[u] = h; pos[u] = hld_pos++; // If u is not a leaf, first decompose its heavy path with head = u's // head. This will guarantee that heavy paths are contiguous in pos[] // array Later this will help to maintain the tree with only one segment // tree if (heavy[u] != -1) decompose(heavy[u], h, hld_pos); for (int v : g[u]) if (v != parent[u] and v != heavy[u]) decompose(v, v, hld_pos); // New heavy path with v as start } // The path from a to b can be decomposed to a -> lca(a, b) + b -> lca(a, // b). This query implementation will force the deepest node to climb up // until both of them are on the same chain, computing partial answers as // they go. Once there one query will do the job. S query(int a, int b) { /* * Query path a to b * * The path from a to b can be decomposed to a -> lca(a, b) + b -> * lca(a, b). This query implementation will force the deepest node to * climb up until both of them are on the same chain, computing partial * answers as they go. Once there one query will do the job. */ S ans = e(); // This loop will allow the deeper node to climb chains until it gets to // a and b's lca. It will compute the partial answers on each chain. while (head[a] != head[b]) // While a and b are on different chains { // We need to find a and b's lca. The node whose chain is furthest // down has to climb up. We will refer as b to that node. Note that // it can stop referring to the same node if the the node that's // climbing becomes less deeper than the other. if (depth[head[a]] > depth[head[b]]) swap(a, b); ans = op(ans, st.prod(pos[head[b]], pos[b] + 1)); b = parent[head[b]]; } // Now both a and b are on the same chain, same trick as before, b will // refer to the deeper node (the one that appears last in the segment // tree). if (depth[a] > depth[b]) swap(a, b); return op(ans, st.prod(pos[a], pos[b] + 1)); } void set(int u, S new_value) { st.set(pos[u], new_value); } S get(int u) { return st.get(pos[u]); } }; } // namespace cplib #endif // CPLIB_HLD_HPP
#line 1 "cplib/data_structure/hld.hpp" #include <algorithm> #include <vector> namespace cplib { using namespace std; template <template <class S, S (*op)(S, S), S (*e)()> class segtree, class S, S (*op)(S, S), S (*e)()> struct HLD { using Tree = vector<vector<int>>; using SegmentTree = segtree<S, op, e>; Tree g; SegmentTree st; vector<int> parent, depth, heavy, head, pos; HLD(int n) : g(n), st(n), parent(n, 0), depth(n, 0), heavy(n, -1), head(n, 0), pos(n, 0) { } HLD(Tree _g) : HLD(_g.size()) { copy(begin(_g), end(_g), begin(g)); } void add_edge(int u, int v) { g[u].push_back(v), g[v].push_back(u); } void operator()(void) { int hld_pos = 0; dfs(0); decompose(0, 0, hld_pos); } int dfs(int u) { /* * Build depth and heavy array. * * u_sz: size of u's subtree * v_sz: size of v's subtree */ int u_sz = 1, mx_v_sz = 0, v_sz; for (int v : g[u]) { if (v != parent[u]) { parent[v] = u; depth[v] = depth[u] + 1; v_sz = dfs(v); u_sz += v_sz; if (v_sz > mx_v_sz) { mx_v_sz = v_sz; heavy[u] = v; } } } return u_sz; } // u: node, h: head of node void decompose(int u, int h, int &hld_pos) { /* * Decompose tree * * u: current node * h: head of node */ head[u] = h; pos[u] = hld_pos++; // If u is not a leaf, first decompose its heavy path with head = u's // head. This will guarantee that heavy paths are contiguous in pos[] // array Later this will help to maintain the tree with only one segment // tree if (heavy[u] != -1) decompose(heavy[u], h, hld_pos); for (int v : g[u]) if (v != parent[u] and v != heavy[u]) decompose(v, v, hld_pos); // New heavy path with v as start } // The path from a to b can be decomposed to a -> lca(a, b) + b -> lca(a, // b). This query implementation will force the deepest node to climb up // until both of them are on the same chain, computing partial answers as // they go. Once there one query will do the job. S query(int a, int b) { /* * Query path a to b * * The path from a to b can be decomposed to a -> lca(a, b) + b -> * lca(a, b). This query implementation will force the deepest node to * climb up until both of them are on the same chain, computing partial * answers as they go. Once there one query will do the job. */ S ans = e(); // This loop will allow the deeper node to climb chains until it gets to // a and b's lca. It will compute the partial answers on each chain. while (head[a] != head[b]) // While a and b are on different chains { // We need to find a and b's lca. The node whose chain is furthest // down has to climb up. We will refer as b to that node. Note that // it can stop referring to the same node if the the node that's // climbing becomes less deeper than the other. if (depth[head[a]] > depth[head[b]]) swap(a, b); ans = op(ans, st.prod(pos[head[b]], pos[b] + 1)); b = parent[head[b]]; } // Now both a and b are on the same chain, same trick as before, b will // refer to the deeper node (the one that appears last in the segment // tree). if (depth[a] > depth[b]) swap(a, b); return op(ans, st.prod(pos[a], pos[b] + 1)); } void set(int u, S new_value) { st.set(pos[u], new_value); } S get(int u) { return st.get(pos[u]); } }; } // namespace cplib