template struct HLD { struct node_info { int father, depth, hson, size, head, dfn = -1; }; int n; vector seq; vector info; segtree tr; // returns: (dfs sequence, node info) // node numbering starts from `1` // if `dfn(v) == -1`, then node `v` is never accessed. HLD(const vector>& ch, const vector& init, int root = 0) : n(ch.size() - 1), seq(), info(n + 1), tr(n + 1) { vector res(n + 1); auto dfs1 = [&] (auto dfs1, int v, int pa) -> void { res[v].father = pa; res[v].depth = res[pa].depth + 1; res[v].size = 1; int mx = 0; for (auto&& u : ch[v]) { if (u == pa) continue; dfs1(dfs1, u, v); res[v].size += res[u].size; if (res[u].size > mx) { mx = res[u].size; res[v].hson = u; } } }; dfs1(dfs1, root, root); int tm = 0; auto dfs2 = [&] (auto dfs2, int v, int head) -> void { res[v].dfn = tm++; seq.emplace_back(v); res[v].head = head; if (not res[v].hson) return; dfs2(dfs2, res[v].hson, head); for (auto&& u : ch[v]) { if (u == res[v].father or u == res[v].hson) continue; dfs2(dfs2, u, u); } }; dfs2(dfs2, root, root); info = res; for (int i = 1; i <= n; ++i) { tr.set(info[i].dfn, init[i]); } } void set(int v, const Info& t) { tr.set(info[v].dfn, t); } void apply(int v, const Tag& t) { tr.apply(info[v].dfn, t); } Info query(int v) { return tr.query(info[v].dfn); } void path_apply(int u, int v, const Tag& t) { while (info[u].head != info[v].head) { if (info[info[u].head].depth < info[info[v].head].depth) { swap(u, v); } tr.range_apply(info[info[u].head].dfn, info[u].dfn, t); u = info[info[u].head].father; } if (info[u].depth < info[v].depth) swap(u, v); tr.range_apply(info[v].dfn, info[u].dfn, t); } Info path_query(int u, int v) { Info res; while (info[u].head != info[v].head) { if (info[info[u].head].depth < info[info[v].head].depth) { swap(u, v); } res = res + tr.range_query(info[info[u].head].dfn, info[u].dfn); u = info[info[u].head].father; } if (info[u].depth < info[v].depth) swap(u, v); res = res + tr.range_query(info[v].dfn, info[u].dfn); return res; } void subtree_apply(int v, const Tag& t) { tr.range_apply(info[v].dfn, info[v].dfn + info[v].size - 1, t); } Info subtree_query(int v) { return tr.range_query(info[v].dfn, info[v].dfn + info[v].size - 1); } };