This documentation is automatically generated by online-judge-tools/verification-helper
 cplib/data_structure/hld.hpp
 cplib/data_structure/hld.hpp
    
#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