This documentation is automatically generated by online-judge-tools/verification-helper
#include "data-structure/HLD.hpp"
#include "../graph/template.hpp"
#include "../SegmentTree/segtree.hpp"
template <class T, T(*op)(const T&,const T&), T(*rev_op)(const T&,const T&), T(*e)()>
struct HLD {
graph root;
int n, in_cnt = 0;
vector<int> pre, sh, sz, p;
SegmentTree<T,op,e> seg;
SegmentTree<T,rev_op,e> rseg;
HLD(const graph &g) : root(g), n(g.size()), pre(n), sh(n), sz(n), p(n), seg(n), rseg(n){
size(0, -1);
calc(0, -1, 0);
}
void size(int pos, int par){
sz[pos] = 1;
int mx = -1, idx = -1, cnt = -1;
for(const int &x : root[pos]){
cnt++;
if(x == par) continue;
size(x, pos);
sz[pos] += sz[x];
if(chmax(mx, sz[x])) idx = cnt;
}
if(idx != -1) swap(root[pos][0], root[pos][idx]);
}
void calc(int pos, int par, int v){
p[pos] = in_cnt++;
sh[pos] = v;
pre[pos] = par;
int cnt = -1;
for(const int &x : root[pos]){
cnt++;
if(x == par) continue;
if(cnt) calc(x, pos, x);
else calc(x, pos, v);
}
}
void set(int u, const T &x){
seg.set(p[u], x);
rseg.set(p[u], x);
}
void build(){
seg.build();
rseg.build();
}
void update(int u, const T &x){
seg.update(p[u], x);
rseg.update(p[u], x);
}
vector<pair<int,int>> query_path(int u, int v){
vector<pair<int,int>> lef, rig;
while(sh[u] != sh[v]){
if(p[u] < p[v]){
rig.emplace_back(p[sh[v]], p[v]);
v = pre[sh[v]];
}
else{
lef.emplace_back(p[u], p[sh[u]]);
u = pre[sh[u]];
}
}
if(p[u] < p[v]) rig.emplace_back(p[u], p[v]);
else lef.emplace_back(p[u], p[v]);
reverse(all(rig));
lef.insert(lef.end(), all(rig));
return lef;
}
T query(int u, int v){
T res = e();
for(const auto &x : query_path(u, v)){
if(x.first <= x.second){
res = op(res, seg.query(x.first, x.second+1));
}else{
res = op(res, rseg.query(x.second, x.first+1));
}
}
return res;
}
T get(const int i){ return seg.get(p[i]); }
};
#line 2 "graph/template.hpp"
/**
* @brief Graph Template
*/
template <class T>
struct Edge {
int from,to;
T cost;
int idx;
Edge(){};
Edge(int f, int t, T c=1, int i=-1) : from(f), to(t), cost(c), idx(i){}
Edge(int t) : to(t), from(-1), cost(1), idx(-1){}
operator int() const{ return to; }
bool operator<(const Edge &e){ return cost < e.cost; }
};
template <class T>
struct Graph : vector<vector<Edge<T>>> {
Graph(){}
Graph(const int &n) : vector<vector<Edge<T>>>(n){}
void add_edge(int a, int b, T c=1, int i=-1){
(*this)[a].push_back({ a, b, c, i });
}
};
using graph = Graph<int>;
#line 1 "SegmentTree/segtree.hpp"
template <class T, T(*op)(const T&,const T&), T(*e)()>
struct SegmentTree {
SegmentTree(const int _n) : n(_n){
while((1 << log) < n) log++;
len = 1 << log;
d.resize(len * 2, e());
}
void update(int k, const T &x){
assert(0 <= k && k < n);
k += len;
d[k] = x;
while(k > 1){
k >>= 1;
d[k] = op(d[k*2], d[k*2+1]);
}
}
void set(const int i, const T &x){
assert(0 <= i && i < n);
d[i + len] = x;
}
T get(const int i) const{
assert(0 <= i && i < n);
return d[i + len];
}
void build(){
for(int k = len - 1; k >= 1; k--)
d[k] = op(d[2*k], d[2*k+1]);
}
T query(int l, int r){
assert(0 <= l && l <= r && r <= n);
l += len; r += len;
T left = e(), right = e();
while(l < r){
if(l & 1) left = op(left, d[l++]);
if(r & 1) right = op(d[--r], right);
l >>= 1; r >>= 1;
}
return op(left, right);
}
template <class F>
int max_right(int l, F f) const{
assert(0 <= l && l <= n);
assert(f(e()));
if(l == n) return n;
l += len;
T sm = e();
do {
l /= l & -l;
if(!f(op(sm, d[l]))){
while(l < len){
l <<= 1;
if(f(op(sm, d[l]))){
sm = op(sm, d[l]);
l++;
}
}
return l - len;
}
sm = op(sm, d[l]);
l++;
}while(l & (l - 1));
return n;
}
template <class F>
int min_left(int r, F f) const{
assert(0 <= r && r <= n);
assert(f(e()));
if(r == 0) return 0;
r += len;
T sm = e();
do {
r /= r & -r;
if(r > 1) r--;
if(!f(op(d[r], sm))){
while(r < len){
r = r * 2 + 1;
if(f(op(d[r], sm))){
sm = op(d[r], sm);
r--;
}
}
return r + 1 - len;
}
sm = op(d[r], sm);
}while(r & (r - 1));
return 0;
}
private:
int n = 1, log = 0, len = 0;
vector<T> d;
};
#line 3 "data-structure/HLD.hpp"
template <class T, T(*op)(const T&,const T&), T(*rev_op)(const T&,const T&), T(*e)()>
struct HLD {
graph root;
int n, in_cnt = 0;
vector<int> pre, sh, sz, p;
SegmentTree<T,op,e> seg;
SegmentTree<T,rev_op,e> rseg;
HLD(const graph &g) : root(g), n(g.size()), pre(n), sh(n), sz(n), p(n), seg(n), rseg(n){
size(0, -1);
calc(0, -1, 0);
}
void size(int pos, int par){
sz[pos] = 1;
int mx = -1, idx = -1, cnt = -1;
for(const int &x : root[pos]){
cnt++;
if(x == par) continue;
size(x, pos);
sz[pos] += sz[x];
if(chmax(mx, sz[x])) idx = cnt;
}
if(idx != -1) swap(root[pos][0], root[pos][idx]);
}
void calc(int pos, int par, int v){
p[pos] = in_cnt++;
sh[pos] = v;
pre[pos] = par;
int cnt = -1;
for(const int &x : root[pos]){
cnt++;
if(x == par) continue;
if(cnt) calc(x, pos, x);
else calc(x, pos, v);
}
}
void set(int u, const T &x){
seg.set(p[u], x);
rseg.set(p[u], x);
}
void build(){
seg.build();
rseg.build();
}
void update(int u, const T &x){
seg.update(p[u], x);
rseg.update(p[u], x);
}
vector<pair<int,int>> query_path(int u, int v){
vector<pair<int,int>> lef, rig;
while(sh[u] != sh[v]){
if(p[u] < p[v]){
rig.emplace_back(p[sh[v]], p[v]);
v = pre[sh[v]];
}
else{
lef.emplace_back(p[u], p[sh[u]]);
u = pre[sh[u]];
}
}
if(p[u] < p[v]) rig.emplace_back(p[u], p[v]);
else lef.emplace_back(p[u], p[v]);
reverse(all(rig));
lef.insert(lef.end(), all(rig));
return lef;
}
T query(int u, int v){
T res = e();
for(const auto &x : query_path(u, v)){
if(x.first <= x.second){
res = op(res, seg.query(x.first, x.second+1));
}else{
res = op(res, rseg.query(x.second, x.first+1));
}
}
return res;
}
T get(const int i){ return seg.get(p[i]); }
};