This documentation is automatically generated by online-judge-tools/verification-helper
#include "Graph/statictoptree.hpp"
#pragma once struct StaticTopTree { using T = array<int, 4>; vector<vector<int>> g; vector<T> tree; // {par,L,R,type 0:rake,1:compress,2:vertex} int n, rt; StaticTopTree() {} StaticTopTree(int n) : n(n), g(n), tree(n) {} void add_edge(int u, int v) { g[u].push_back(v); g[v].push_back(u); } void run(int base = 0) { dfs(base, -1); rt = build(base).first; } void dump() { rep(v, 0, SZ(tree)) { auto [par, L, R, type] = tree[v]; show(v, par, L, R, type); } } private: int dfs(int v, int p) { rep(i, 0, SZ(g[v])) if (g[v][i] == p) { g[v].erase(g[v].begin() + i); break; } int sz = 1, best = 0; for (auto &to : g[v]) { int add = dfs(to, v); sz += add; if (chmax(best, add)) swap(to, g[v].front()); } return sz; } using P = pair<int, int>; // {ID,size} int make(int v, int L, int R, int type) { if (v == -1) { v = SZ(tree); tree.push_back({-1, L, R, type}); } else { tree[v] = {-1, L, R, type}; } if (L != -1) tree[L][0] = v; if (R != -1) tree[R][0] = v; return v; } P merge(vector<P> a, int type) { if (SZ(a) == 1) return a[0]; int sum = 0; for (auto &[_, sz] : a) sum += sz; vector<P> L, R; for (auto &[v, sz] : a) { if (sum > sz) L.push_back({v, sz}); else R.push_back({v, sz}); sum -= sz * 2; } auto [lb, ls] = merge(L, type); auto [rb, rs] = merge(R, type); return P{make(-1, lb, rb, type), ls + rs}; } P build(int v) { int cur = v, pre = -1; vector<P> a; for (;;) { // rake vector<P> b; b.push_back({make(cur, -1, -1, 2), 1}); if (pre != -1) { assert(g[pre][0] == cur); for (auto &to : g[pre]) if (to != cur) { b.push_back(build(to)); } } a.push_back(merge(b, 0)); if (SZ(g[cur]) == 0) break; pre = cur, cur = g[cur][0]; } return merge(a, 1); } }; /** * rake: (a<-b], (a<-c] -> (a<-b]. * compress: (a<-b], (b<-c] -> (a<-c]. */ template <typename M, M (*rake)(M, M), M (*compress)(M, M)> struct DynamicTreeDP { int n, sz; StaticTopTree stt; vector<M> dat; DynamicTreeDP() {} template <typename F> DynamicTreeDP(int n, StaticTopTree _stt, F vertex) : n(n), sz(SZ(_stt.tree)), stt(_stt), dat(sz) { rep(i, 0, n) dat[i] = vertex(i); rep(i, n, sz) update(i); } void set(int v, M x) { dat[v] = x; for (int p = stt.tree[v][0]; p != -1; p = stt.tree[p][0]) update(p); } M get() { return dat.back(); } private: void update(int v) { auto L = dat[stt.tree[v][1]]; auto R = dat[stt.tree[v][2]]; if (stt.tree[v][3]) { dat[v] = compress(L, R); } else { dat[v] = rake(L, R); } } }; /** * rake1: (a<-b], (a<-c] -> (a<-b]. * rake2: (a->b], (a<-c] -> (a->b]. * compress: (a<-b], (b<-c] -> (a<-c]. */ template <typename M, M (*rake1)(M, M), M (*rake2)(M, M), M (*compress)(M, M), M (*e)()> struct DynamicRerootingDP { int n, sz; StaticTopTree stt; using P = pair<M, M>; vector<P> dat; // {ord,rev} DynamicRerootingDP() {} template <typename F> DynamicRerootingDP(int n, StaticTopTree _stt, F vertex) : n(n), sz(SZ(_stt.tree)), stt(_stt), dat(sz) { dat[0] = {e(), e()}; rep(i, 1, n) dat[i] = vertex(i); rep(i, n, sz) update(i); } void set(int v, P x) { dat[v] = x; for (int p = stt.tree[v][0]; p != -1; p = stt.tree[p][0]) update(p); } M get(int v) { // a: expose cur to v (down) // b: expose from cur (down) // c: expose to cur (up) int cur = v; M a = dat[cur].second, b = e(), c = e(); for (;;) { int p = stt.tree[cur][0]; if (p == -1) break; int L = stt.tree[p][1], R = stt.tree[p][2]; if (stt.tree[p][3]) { if (L == cur) b = compress(b, dat[R].first); else a = compress(a, dat[L].second); } else { if (L == cur) { a = rake2(a, dat[R].first); } else { c = compress(c, rake1(a, b)); a = e(); b = dat[L].first; } } cur = p; } return compress(c, rake1(a, b)); } private: void update(int v) { auto [L, Lre] = dat[stt.tree[v][1]]; auto [R, Rre] = dat[stt.tree[v][2]]; if (stt.tree[v][3]) { dat[v] = P{compress(L, R), compress(Rre, Lre)}; } else { dat[v] = P{rake1(L, R), rake2(Lre, R)}; } } }; /** * @brief Static TopTree */
#line 2 "Graph/statictoptree.hpp" struct StaticTopTree { using T = array<int, 4>; vector<vector<int>> g; vector<T> tree; // {par,L,R,type 0:rake,1:compress,2:vertex} int n, rt; StaticTopTree() {} StaticTopTree(int n) : n(n), g(n), tree(n) {} void add_edge(int u, int v) { g[u].push_back(v); g[v].push_back(u); } void run(int base = 0) { dfs(base, -1); rt = build(base).first; } void dump() { rep(v, 0, SZ(tree)) { auto [par, L, R, type] = tree[v]; show(v, par, L, R, type); } } private: int dfs(int v, int p) { rep(i, 0, SZ(g[v])) if (g[v][i] == p) { g[v].erase(g[v].begin() + i); break; } int sz = 1, best = 0; for (auto &to : g[v]) { int add = dfs(to, v); sz += add; if (chmax(best, add)) swap(to, g[v].front()); } return sz; } using P = pair<int, int>; // {ID,size} int make(int v, int L, int R, int type) { if (v == -1) { v = SZ(tree); tree.push_back({-1, L, R, type}); } else { tree[v] = {-1, L, R, type}; } if (L != -1) tree[L][0] = v; if (R != -1) tree[R][0] = v; return v; } P merge(vector<P> a, int type) { if (SZ(a) == 1) return a[0]; int sum = 0; for (auto &[_, sz] : a) sum += sz; vector<P> L, R; for (auto &[v, sz] : a) { if (sum > sz) L.push_back({v, sz}); else R.push_back({v, sz}); sum -= sz * 2; } auto [lb, ls] = merge(L, type); auto [rb, rs] = merge(R, type); return P{make(-1, lb, rb, type), ls + rs}; } P build(int v) { int cur = v, pre = -1; vector<P> a; for (;;) { // rake vector<P> b; b.push_back({make(cur, -1, -1, 2), 1}); if (pre != -1) { assert(g[pre][0] == cur); for (auto &to : g[pre]) if (to != cur) { b.push_back(build(to)); } } a.push_back(merge(b, 0)); if (SZ(g[cur]) == 0) break; pre = cur, cur = g[cur][0]; } return merge(a, 1); } }; /** * rake: (a<-b], (a<-c] -> (a<-b]. * compress: (a<-b], (b<-c] -> (a<-c]. */ template <typename M, M (*rake)(M, M), M (*compress)(M, M)> struct DynamicTreeDP { int n, sz; StaticTopTree stt; vector<M> dat; DynamicTreeDP() {} template <typename F> DynamicTreeDP(int n, StaticTopTree _stt, F vertex) : n(n), sz(SZ(_stt.tree)), stt(_stt), dat(sz) { rep(i, 0, n) dat[i] = vertex(i); rep(i, n, sz) update(i); } void set(int v, M x) { dat[v] = x; for (int p = stt.tree[v][0]; p != -1; p = stt.tree[p][0]) update(p); } M get() { return dat.back(); } private: void update(int v) { auto L = dat[stt.tree[v][1]]; auto R = dat[stt.tree[v][2]]; if (stt.tree[v][3]) { dat[v] = compress(L, R); } else { dat[v] = rake(L, R); } } }; /** * rake1: (a<-b], (a<-c] -> (a<-b]. * rake2: (a->b], (a<-c] -> (a->b]. * compress: (a<-b], (b<-c] -> (a<-c]. */ template <typename M, M (*rake1)(M, M), M (*rake2)(M, M), M (*compress)(M, M), M (*e)()> struct DynamicRerootingDP { int n, sz; StaticTopTree stt; using P = pair<M, M>; vector<P> dat; // {ord,rev} DynamicRerootingDP() {} template <typename F> DynamicRerootingDP(int n, StaticTopTree _stt, F vertex) : n(n), sz(SZ(_stt.tree)), stt(_stt), dat(sz) { dat[0] = {e(), e()}; rep(i, 1, n) dat[i] = vertex(i); rep(i, n, sz) update(i); } void set(int v, P x) { dat[v] = x; for (int p = stt.tree[v][0]; p != -1; p = stt.tree[p][0]) update(p); } M get(int v) { // a: expose cur to v (down) // b: expose from cur (down) // c: expose to cur (up) int cur = v; M a = dat[cur].second, b = e(), c = e(); for (;;) { int p = stt.tree[cur][0]; if (p == -1) break; int L = stt.tree[p][1], R = stt.tree[p][2]; if (stt.tree[p][3]) { if (L == cur) b = compress(b, dat[R].first); else a = compress(a, dat[L].second); } else { if (L == cur) { a = rake2(a, dat[R].first); } else { c = compress(c, rake1(a, b)); a = e(); b = dat[L].first; } } cur = p; } return compress(c, rake1(a, b)); } private: void update(int v) { auto [L, Lre] = dat[stt.tree[v][1]]; auto [R, Rre] = dat[stt.tree[v][2]]; if (stt.tree[v][3]) { dat[v] = P{compress(L, R), compress(Rre, Lre)}; } else { dat[v] = P{rake1(L, R), rake2(Lre, R)}; } } }; /** * @brief Static TopTree */