47#include <gtest/gtest.h>
53using namespace testing;
79 auto *
u2 =
lct2.make_vertex(2);
88 auto * u = lct.make_vertex(1);
89 auto * v = lct.make_vertex(2);
95 EXPECT_EQ(lct.find_root(u), lct.find_root(v));
101 auto * u = lct.make_vertex(1);
102 auto * v = lct.make_vertex(2);
113 constexpr int N = 10;
114 std::vector<Link_Cut_Tree::Node *>
nd(
N);
115 for (
int i = 0; i <
N; ++i)
116 nd[i] = lct.make_vertex(i);
118 for (
int i = 0; i + 1 <
N; ++i)
119 lct.link(
nd[i],
nd[i + 1]);
121 for (
int i = 0; i <
N; ++i)
122 for (
int j = i; j <
N; ++j)
126 static_cast<size_t>(j - i + 1));
133 std::vector<Link_Cut_Tree::Node *>
nd(
N);
134 for (
int i = 0; i <
N; ++i)
135 nd[i] = lct.make_vertex(i);
138 for (
int i = 0; i + 1 <
N; ++i)
139 lct.link(
nd[i],
nd[i + 1]);
142 lct.cut(
nd[2],
nd[3]);
148 lct.link(
nd[2],
nd[3]);
154 auto * center = lct.make_vertex(0);
156 std::vector<Link_Cut_Tree::Node *>
leaves(
N);
157 for (
int i = 0; i <
N; ++i)
159 leaves[i] = lct.make_vertex(i + 1);
160 lct.link(
leaves[i], center);
163 for (
int i = 0; i <
N; ++i)
166 for (
int i = 0; i <
N; ++i)
167 for (
int j = i + 1; j <
N; ++j)
171 for (
int i = 0; i <
N; ++i)
173 lct.cut(
leaves[i], center);
186 std::vector<Link_Cut_Tree::Node *>
nd(
N);
187 for (
int i = 0; i <
N; ++i)
188 nd[i] = lct.make_vertex(i);
189 for (
int i = 0; i + 1 <
N; ++i)
190 lct.link(
nd[i],
nd[i + 1]);
193 lct.make_root(
nd[3]);
201 std::vector<Link_Cut_Tree::Node *>
nd(
N);
202 for (
int i = 0; i <
N; ++i)
203 nd[i] = lct.make_vertex(i);
204 for (
int i = 0; i + 1 <
N; ++i)
205 lct.link(
nd[i],
nd[i + 1]);
207 for (
int r = 0;
r <
N; ++
r)
209 lct.make_root(
nd[
r]);
211 for (
int i = 0; i <
N; ++i)
219 std::vector<Link_Cut_Tree::Node *>
nd(
N);
220 for (
int i = 0; i <
N; ++i)
221 nd[i] = lct.make_vertex(i);
222 for (
int i = 0; i + 1 <
N; ++i)
223 lct.link(
nd[i],
nd[i + 1]);
225 for (
int r =
N - 1;
r >= 0; --
r)
227 lct.make_root(
nd[
r]);
228 for (
int i = 0; i <
N; ++i)
239 auto * x = lct.make_vertex(1);
247 std::vector<Link_Cut_Tree::Node *>
nd(
N);
248 for (
int i = 0; i <
N; ++i)
249 nd[i] = lct.make_vertex(i);
250 for (
int i = 0; i + 1 <
N; ++i)
251 lct.link(
nd[i],
nd[i + 1]);
253 lct.make_root(
nd[0]);
255 for (
int i = 0; i <
N; ++i)
256 for (
int j = i; j <
N; ++j)
267 auto * n0 = lct.make_vertex(0);
268 auto * n1 = lct.make_vertex(1);
269 auto * n2 = lct.make_vertex(2);
270 auto * n3 = lct.make_vertex(3);
271 auto * n4 = lct.make_vertex(4);
291 auto * u = lct.make_vertex(1);
292 auto * v = lct.make_vertex(2);
299 auto * x = lct.make_vertex(1);
305 auto * u = lct.make_vertex(1);
306 auto * v = lct.make_vertex(2);
307 auto *
w = lct.make_vertex(3);
320 EXPECT_THROW(lct.make_root(
nullptr), std::invalid_argument);
321 EXPECT_THROW(lct.find_root(
nullptr), std::invalid_argument);
322 EXPECT_THROW(lct.connected(
nullptr,
nullptr), std::invalid_argument);
323 auto * x = lct.make_vertex(1);
324 EXPECT_THROW(lct.link(
nullptr, x), std::invalid_argument);
325 EXPECT_THROW(lct.cut(
nullptr, x), std::invalid_argument);
326 EXPECT_THROW(lct.lca(
nullptr, x), std::invalid_argument);
331 auto * u = lct.make_vertex(1);
332 auto * v = lct.make_vertex(2);
338 auto * u = lct.make_vertex(1);
339 auto * v = lct.make_vertex(2);
345 EXPECT_THROW(lct.for_each_on_path(u, v, [&](
auto *) { called = true; }),
358 auto * a = lct.make_vertex(1);
359 auto * b = lct.make_vertex(2);
360 auto * c = lct.make_vertex(3);
375 auto * a = lct.make_vertex(1);
376 auto * b = lct.make_vertex(2);
377 auto * c = lct.make_vertex(3);
397 std::vector<Link_Cut_Tree::Node *>
nd(
N);
398 for (
int i = 0; i <
N; ++i)
399 nd[i] = lct.make_vertex(i);
400 for (
int i = 0; i + 1 <
N; ++i)
401 lct.link(
nd[i],
nd[i + 1]);
403 lct.make_root(
nd[0]);
404 for (
int i = 0; i <
N; ++i)
405 EXPECT_EQ(lct.depth(
nd[i]),
static_cast<size_t>(i));
408 lct.make_root(
nd[2]);
409 for (
int i = 0; i <
N; ++i)
410 EXPECT_EQ(lct.depth(
nd[i]),
static_cast<size_t>(std::abs(i - 2)));
417 std::vector<Link_Cut_Tree::Node *>
nd(
N);
418 for (
int i = 0; i <
N; ++i)
419 nd[i] = lct.make_vertex(i);
420 for (
int i = 0; i + 1 <
N; ++i)
421 lct.link(
nd[i],
nd[i + 1]);
423 lct.make_root(
nd[0]);
430 lct.make_root(
nd[3]);
441 auto * center = lct.make_vertex(0);
442 auto *
l1 = lct.make_vertex(1);
443 auto *
l2 = lct.make_vertex(2);
444 auto *
l3 = lct.make_vertex(3);
446 lct.make_root(center);
447 lct.link(
l1, center);
448 lct.link(
l2, center);
449 lct.link(
l3, center);
464 std::vector<Link_Cut_Tree::Node *>
nd(
N);
465 for (
int i = 0; i <
N; ++i)
466 nd[i] = lct.make_vertex(i);
467 for (
int i = 0; i + 1 <
N; ++i)
468 lct.link(
nd[i],
nd[i + 1]);
472 lct.for_each_on_path(
nd[1],
nd[3],
498 auto path = lct.make_path({10, 20, 30, 40});
502 EXPECT_EQ(lct.path_size(path(0), path(3)), 4u);
509 auto verts = lct.make_vertices({1, 2, 3});
517 auto verts = lct.make_vertices({1, 2, 3, 4});
519 std::vector<std::pair<Link_Cut_Tree::Node *, Link_Cut_Tree::Node *>> edges = {
524 lct.link_edges(edges);
542 auto * x = lct.make_vertex(7);
551 std::vector<NodePtr>
nd(
N);
552 for (
int i = 0; i <
N; ++i)
553 nd[i] = lct.make_vertex(i + 1);
554 for (
int i = 0; i + 1 <
N; ++i)
555 lct.link(
nd[i],
nd[i + 1]);
567 auto * u = lct.make_vertex(10);
568 auto * v = lct.make_vertex(20);
579 auto * a = lct.make_vertex(1);
580 auto * b = lct.make_vertex(2);
581 auto * c = lct.make_vertex(3);
608 std::vector<NodePtr>
nd(
N);
609 int vals[] = {7, 2, 9, 1, 5};
610 for (
int i = 0; i <
N; ++i)
611 nd[i] = lct.make_vertex(
vals[i]);
612 for (
int i = 0; i + 1 <
N; ++i)
613 lct.link(
nd[i],
nd[i + 1]);
634 std::vector<NodePtr>
nd(
N);
635 int vals[] = {3, 8, 1, 6, 4};
636 for (
int i = 0; i <
N; ++i)
637 nd[i] = lct.make_vertex(
vals[i]);
638 for (
int i = 0; i + 1 <
N; ++i)
639 lct.link(
nd[i],
nd[i + 1]);
657 auto * a = lct.make_vertex(5);
658 auto * b = lct.make_vertex(3);
659 auto * c = lct.make_vertex(6);
664 EXPECT_EQ(lct.path_query(a, c), 5 ^ 3 ^ 6);
680 auto * a = lct.make_vertex(12);
681 auto * b = lct.make_vertex(18);
682 auto * c = lct.make_vertex(24);
707 auto * a = lct.make_vertex(2LL);
708 auto * b = lct.make_vertex(3LL);
709 auto * c = lct.make_vertex(5LL);
736 std::vector<NodePtr>
nd(
N);
737 for (
int i = 0; i <
N; ++i)
738 nd[i] = lct.make_vertex(0
LL);
739 for (
int i = 0; i + 1 <
N; ++i)
740 lct.link(
nd[i],
nd[i + 1]);
743 lct.path_apply(
nd[0],
nd[4], 10LL);
747 lct.path_apply(
nd[1],
nd[3], 5LL);
757 auto * u = lct.make_vertex(1LL);
758 auto * v = lct.make_vertex(2LL);
759 EXPECT_THROW(lct.path_apply(u, v, 5LL), std::domain_error);
780 std::vector<NodePtr>
nd(
N);
781 for (
int i = 0; i <
N; ++i)
782 nd[i] = lct.make_vertex(
static_cast<long long>(i + 1));
783 for (
int i = 0; i + 1 <
N; ++i)
784 lct.link(
nd[i],
nd[i + 1]);
813 std::vector<std::vector<int>> adj;
815 explicit NaiveForest(
int n) : n(n), adj(n) {}
817 void link(
int u,
int v)
823 void cut(
int u,
int v)
825 adj[u].erase(std::find(adj[u].begin(), adj[u].end(), v));
826 adj[v].erase(std::find(adj[v].begin(), adj[v].end(), u));
829 bool connected(
int u,
int v)
const
833 std::vector<bool> visited(n,
false);
834 std::vector<int>
stk = {u};
840 for (
int nb : adj[
cur])
854 return std::find(adj[u].begin(), adj[u].end(), v) != adj[u].end();
862 constexpr int N = 200;
863 constexpr int OPS = 2000;
865 std::mt19937
rng(12345);
868 std::vector<Link_Cut_Tree::Node *>
nd(
N);
869 for (
int i = 0; i <
N; ++i)
875 std::vector<std::pair<int, int>> edges;
877 for (
int op = 0; op <
OPS; ++op)
879 int choice = std::uniform_int_distribution<int>(0, 2)(
rng);
881 if (
choice == 0
and edges.size() <
static_cast<size_t>(
N - 1))
884 int u = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
885 int v = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
890 edges.push_back({u, v});
896 size_t idx = std::uniform_int_distribution<size_t>(
897 0, edges.size() - 1)(
rng);
898 auto [u, v] = edges[idx];
899 edges[idx] = edges.back();
908 int u = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
909 int v = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
912 <<
"mismatch at op=" << op <<
" u=" << u <<
" v=" << v;
927 std::vector<int> val;
928 std::vector<std::vector<int>> adj;
930 explicit NaiveSumForest(
int n) : n(n), val(n, 0), adj(n) {}
932 void link(
int u,
int v) { adj[u].push_back(v); adj[v].push_back(u); }
933 void cut(
int u,
int v)
935 adj[u].erase(std::find(adj[u].begin(), adj[u].end(), v));
936 adj[v].erase(std::find(adj[v].begin(), adj[v].end(), u));
939 bool connected(
int u,
int v)
const
941 if (u == v)
return true;
942 std::vector<bool>
vis(n,
false);
943 std::vector<int>
stk = {u};
947 int c =
stk.back();
stk.pop_back();
948 for (
int nb : adj[c])
950 {
if (
nb == v)
return true;
vis[
nb] =
true;
stk.push_back(
nb); }
958 std::vector<int> par(n, -1);
959 std::vector<bool>
vis(n,
false);
960 std::vector<int> q = {u};
962 while (
not q.empty())
964 int c = q.back(); q.pop_back();
966 for (
int nb : adj[c])
968 {
vis[
nb] =
true; par[
nb] = c; q.push_back(
nb); }
971 for (
int c = v; c != -1; c = par[c])
981 constexpr int N = 100;
982 constexpr int OPS = 1000;
984 std::mt19937
rng(54321);
988 std::vector<NodePtr>
nd(
N);
992 for (
int i = 0; i <
N; ++i)
994 int v = std::uniform_int_distribution<int>(1, 100)(
rng);
1000 std::vector<std::pair<int, int>> edges;
1001 std::vector<int>
perm(
N);
1002 std::iota(
perm.begin(),
perm.end(), 0);
1004 for (
int i = 1; i <
N; ++i)
1006 int par =
perm[std::uniform_int_distribution<int>(0, i - 1)(
rng)];
1010 edges.push_back({
cur, par});
1013 for (
int op = 0; op <
OPS; ++op)
1015 int choice = std::uniform_int_distribution<int>(0, 3)(
rng);
1020 int u = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1021 int v = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1022 if (
oracle.connected(u, v))
1027 <<
"path_sum mismatch at op=" << op
1028 <<
" u=" << u <<
" v=" << v;
1034 int idx = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1035 int nv = std::uniform_int_distribution<int>(1, 100)(
rng);
1042 size_t ei = std::uniform_int_distribution<size_t>(
1043 0, edges.size() - 1)(
rng);
1044 auto [u, v] = edges[
ei];
1045 edges[
ei] = edges.back();
1050 else if (
choice == 3
and edges.size() <
static_cast<size_t>(
N - 1))
1053 int u = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1054 int v = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1059 edges.push_back({u, v});
1071 constexpr int N = 50000;
1073 std::vector<Link_Cut_Tree::Node *>
nd(
N);
1074 for (
int i = 0; i <
N; ++i)
1078 for (
int i = 0; i + 1 <
N; ++i)
1097 for (
int i = 0; i < 512; ++i)
1117 auto * u = lct.make_vertex(0);
1118 auto * v = lct.make_vertex(1);
1127 auto * u = lct.make_vertex(10);
1128 auto * v = lct.make_vertex(20);
1133 lct.set_vertex_val(v, 25);
1145 auto * u = lct.make_vertex(0);
1146 auto * v = lct.make_vertex(1);
1147 auto *
w = lct.make_vertex(2);
1160 auto * u = lct.make_vertex(0);
1161 auto * v = lct.make_vertex(1);
1174 auto * u = lct.make_vertex(0);
1175 auto * v = lct.make_vertex(1);
1177 lct.link(u, v, 100);
1191 auto *
v0 = lct.make_vertex(0);
1192 auto * v1 = lct.make_vertex(1);
1193 auto * v2 = lct.make_vertex(2);
1196 lct.link(
v0, v1, 2);
1197 lct.link(v1, v2, 3);
1211 auto * a = lct.make_vertex(100);
1212 auto * b = lct.make_vertex(101);
1213 auto * c = lct.make_vertex(102);
1214 auto * d = lct.make_vertex(103);
1234 auto * u = lct.make_vertex(0);
1235 auto * v = lct.make_vertex(1);
1236 auto *
w = lct.make_vertex(2);
1243 lct.set_edge_val(u, v, 1);
1252 auto * a = lct.make_vertex(0);
1253 auto * b = lct.make_vertex(1);
1254 auto * c = lct.make_vertex(2);
1270 auto * u = lct.make_vertex(0);
1271 auto * v = lct.make_vertex(1);
1274 EXPECT_THROW(lct.link(u, u, 1), std::invalid_argument);
1277 EXPECT_THROW(lct.link(
nullptr, v, 1), std::invalid_argument);
1284 auto *
w = lct.make_vertex(2);
1295struct NaiveEdgeForest
1298 struct Edge {
int u, v,
w; };
1299 std::vector<Edge> edges;
1300 std::vector<std::vector<std::pair<int, int>>> adj;
1302 explicit NaiveEdgeForest(
int n) : n(n), adj(n) {}
1304 void link(
int u,
int v,
int w)
1306 int idx =
static_cast<int>(edges.size());
1307 edges.push_back({u, v,
w});
1308 adj[u].push_back({v, idx});
1309 adj[v].push_back({u, idx});
1312 void cut(
int u,
int v)
1314 for (
auto it = adj[u].begin(); it != adj[u].end(); ++it)
1315 if (it->first == v) { adj[u].erase(it);
break; }
1316 for (
auto it = adj[v].begin(); it != adj[v].end(); ++it)
1317 if (it->first == u) { adj[v].erase(it);
break; }
1320 bool connected(
int u,
int v)
const
1322 if (u == v)
return true;
1323 std::vector<bool>
vis(n,
false);
1324 std::vector<int>
stk = {u};
1328 int c =
stk.back();
stk.pop_back();
1329 for (
auto [
nb,
_] : adj[c])
1331 {
if (
nb == v)
return true;
vis[
nb] =
true;
stk.push_back(
nb); }
1338 for (
auto [
nb,
_] : adj[u])
1345 std::vector<int> par(n, -1);
1347 std::vector<bool>
vis(n,
false);
1348 std::vector<int> q = {u};
1350 while (
not q.empty())
1352 int c = q.back(); q.pop_back();
1354 for (
auto [
nb,
eidx] : adj[c])
1358 int mx = std::numeric_limits<int>::lowest();
1359 for (
int c = v; par[c] != -1; c = par[c])
1369 constexpr int N = 100;
1370 constexpr int OPS = 1500;
1372 std::mt19937
rng(99887);
1376 std::vector<NodePtr>
nd(
N);
1377 for (
int i = 0; i <
N; ++i)
1383 for (
int op = 0; op <
OPS; ++op)
1385 int choice = std::uniform_int_distribution<int>(0, 2)(
rng);
1389 int u = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1390 int v = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1393 int w = std::uniform_int_distribution<int>(1, 1000)(
rng);
1401 size_t idx = std::uniform_int_distribution<size_t>(
1412 int u = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1413 int v = std::uniform_int_distribution<int>(0,
N - 1)(
rng);
1419 <<
"path_max mismatch at op=" << op
1420 <<
" u=" << u <<
" v=" << v;
1438 constexpr int N = 5;
1439 std::vector<Link_Cut_Tree::Node *>
nd(
N);
1440 for (
int i = 0; i <
N; ++i)
1441 nd[i] = lct.make_vertex(i * 10);
1442 for (
int i = 0; i + 1 <
N; ++i)
1443 lct.link(
nd[i],
nd[i + 1]);
1445 auto * tree = lct.export_to_tree_node(
nd[0]);
1452 auto * c = tree->get_left_child();
1456 c = c->get_left_child();
1460 c = c->get_left_child();
1464 c = c->get_left_child();
1477 auto * center = lct.make_vertex(100);
1478 auto *
l1 = lct.make_vertex(10);
1479 auto *
l2 = lct.make_vertex(20);
1480 auto *
l3 = lct.make_vertex(30);
1482 lct.make_root(center);
1483 lct.link(
l1, center);
1484 lct.link(
l2, center);
1485 lct.link(
l3, center);
1487 auto * tree = lct.export_to_tree_node(center);
1494 for (
auto * c = tree->get_left_child(); c !=
nullptr;
1495 c = c->get_right_sibling())
1517 auto * a = lct.make_vertex(0);
1518 auto * b = lct.make_vertex(1);
1519 auto * c = lct.make_vertex(2);
1520 auto * d = lct.make_vertex(3);
1526 auto * tree = lct.export_to_tree_node(a);
1533 auto *
cb = tree->get_left_child();
1540 auto *
cc =
cb->get_left_child();
1547 auto * cd =
cc->get_left_child();
1550 EXPECT_EQ(cd->get_key().vertex_value, 3);
1551 EXPECT_EQ(cd->get_key().parent_edge, 7);
1563 auto * center = lct.make_vertex(0);
1564 auto * x = lct.make_vertex(1);
1565 auto *
y = lct.make_vertex(2);
1566 auto * z = lct.make_vertex(3);
1568 lct.link(x, center, 10);
1569 lct.link(
y, center, 20);
1570 lct.link(z, center, 30);
1572 auto * tree = lct.export_to_tree_node(center);
1573 EXPECT_EQ(tree->get_key().lct_node, center);
1576 for (
auto * c = tree->get_left_child(); c !=
nullptr;
1577 c = c->get_right_sibling())
1595 auto * a = lct.make_vertex(0);
1596 auto * b = lct.make_vertex(1);
1597 auto * c = lct.make_vertex(2);
1613 auto * a = lct.make_vertex(0);
1614 auto * b = lct.make_vertex(1);
1615 auto * c = lct.make_vertex(2);
1633 auto * a = lct.make_vertex(0);
1634 auto * b = lct.make_vertex(1);
1635 auto * c = lct.make_vertex(2);
1636 auto * d = lct.make_vertex(3);
1650 auto * a = lct.make_vertex(0);
1651 auto * b = lct.make_vertex(1);
1652 auto * c = lct.make_vertex(2);
1674 auto * v1 =
lct1.make_vertex(3);
1675 auto *
u2 =
lct2.make_vertex(2);
1693 ::testing::InitGoogleTest(&
argc,
argv);
WeightedDigraph::Node Node
Link-Cut Tree with edge weights and path aggregations.
void cut(Node *u, Node *v)
Remove the edge between u and v.
bool connected(Node *u, Node *v)
Test whether u and v are in the same tree.
ET path_query(Node *u, Node *v)
Aggregate edge values on the path from u to v.
Node * make_vertex(const VT &val=VT{})
Create an isolated vertex.
void link(Node *u, Node *v, const ET &weight)
Add an edge (u, v) with weight weight.
Dynamic forest with path queries via Link-Cut Trees.
void set_val(Node *x, const T &val)
Update the payload value of vertex x and recompute aggregates.
size_t path_size(Node *u, Node *v)
Number of vertices on the path from u to v.
void make_root(Node *x)
Make x the root of its represented tree.
T path_query(Node *u, Node *v)
Aggregate (under Monoid) over all vertex values on the path from u to v.
Node * find_root(Node *x)
Find the root of the represented tree containing x.
bool connected(Node *u, Node *v)
Test whether u and v are in the same represented tree.
Node * make_vertex(const T &val=T{})
Create an isolated vertex with payload val.
void link(Node *u, Node *v)
Add an edge between u and v, merging their trees.
void cut(Node *u, Node *v)
Remove the represented edge between u and v.
Gen_Link_Cut_Tree< long long, SumMonoid< long long >, AssignLazyTag< long long > > lct
Gen_Link_Cut_Tree_WithEdges< int, int, MaxMonoid< int > > lct
Gen_Link_Cut_Tree< int, GcdMonoid< int > > lct
Gen_Link_Cut_Tree< long long, SumMonoid< long long >, AddLazyTag< long long > > lct
Gen_Link_Cut_Tree< int, MaxMonoid< int > > lct
Gen_Link_Cut_Tree< int, MinMonoid< int > > lct
Gen_Link_Cut_Tree< long long, ProductMonoid< long long > > lct
Gen_Link_Cut_Tree< int, SumMonoid< int > > lct
Gen_Link_Cut_Tree< int, XorMonoid< int > > lct
void destroy_tree(Node *root)
Destroys (frees memory) the tree whose root is root.
TEST_F(LinkCutTreeStructTest, SingleNodeIsItsOwnRoot)
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Additive lazy tag: adds a delta to every node on a path.
Payload for the assignment lazy tag.
Assignment lazy tag: sets every node on a path to a fixed value.
Internal node of the Link-Cut Tree (opaque handle).
Link-Cut Tree: a dynamic forest with path queries.
Edge-weighted Link-Cut Tree using edge-as-node representation.