83 std::vector<std::list<int>>
87 std::vector<std::vector<int>>
104 for (
const int &v :
t_adj[u]) {
124 if (
t_par[u][k - 1] != -1) {
129 for (
const int &v :
t_adj[u]) {
160 t_adj[u].push_back(v);
161 t_adj[v].push_back(u);
178 assert(
static_cast<int>(node_val.size()) ==
t_nodes);
202 void lift(
int *
const p,
int dist) {
242 for (
int k =
t_maxlift - 1; k >= 0; k--) {
268 template <
typename T>
286 explicit SG(
int size) {
298 for (p +=
s_size; p > 0; p >>= 1) {
311 for (l +=
s_size, r +=
s_size + 1; l < r; l >>= 1, r >>= 1) {
357 int hc_size = -1, hc_id = -1;
441 explicit HLD(
int nodes) :
Tree<X>(nodes),
SG<X>(nodes) {
466 for (
int i = 0; i < Tree<X>::t_nodes; i++) {
512 std::cout <<
"Test 1:\n";
516 std::vector<int64_t> node_values = {4, 2, 5, 2, 1};
517 std::vector<std::vector<int>> edges = {{1, 2}, {1, 3}, {3, 4}, {3, 5}};
518 std::vector<std::vector<int>> queries = {
523 std::vector<int> expected_result = {11, 8};
524 std::vector<int> code_result;
528 for (
int i = 0; i < n - 1; i++) {
529 int u = edges[i][0], v = edges[i][1];
533 for (
const auto &q : queries) {
536 int p = q[1], x = q[2];
538 }
else if (type == 2) {
539 int a = q[1], b = q[2];
540 code_result.push_back(hld.
query(a - 1, b - 1));
545 for (
int i = 0; i < static_cast<int>(expected_result.size()); i++) {
546 assert(expected_result[i] == code_result[i]);
548 std::cout <<
"\nTest 1 passed!\n";
556 std::cout <<
"Test 2:\n";
560 std::vector<int64_t> node_values = {1, 8, 6, 8, 6, 2, 9, 2, 3, 2};
561 std::vector<std::vector<int>> edges = {{10, 5}, {6, 2}, {10, 7},
562 {5, 2}, {3, 9}, {8, 3},
563 {1, 4}, {6, 4}, {8, 7}};
564 std::vector<std::vector<int>> queries = {
565 {2, 1, 10}, {2, 1, 6}, {1, 3, 4}, {2, 1, 9}, {1, 5, 3},
566 {1, 7, 8}, {2, 1, 4}, {2, 1, 8}, {1, 1, 4}, {1, 2, 7}};
567 std::vector<int> expected_result = {27, 11, 45, 9, 34};
568 std::vector<int> code_result;
572 for (
int i = 0; i < n - 1; i++) {
573 int u = edges[i][0], v = edges[i][1];
577 for (
const auto &q : queries) {
580 int p = q[1], x = q[2];
582 }
else if (type == 2) {
583 int a = q[1], b = q[2];
584 code_result.push_back(hld.
query(a - 1, b - 1));
589 for (
int i = 0; i < static_cast<int>(expected_result.size()); i++) {
590 assert(expected_result[i] == code_result[i]);
592 std::cout <<
"\nTest2 passed!\n";
600 std::cout <<
"Test 3:\n";
604 std::vector<int64_t> node_values = {1, 8, 6, 8, 6, 2, 9, 2};
605 std::vector<std::vector<int>> edges = {{1, 2}, {2, 3}, {3, 4}, {1, 5},
606 {6, 3}, {7, 5}, {8, 7}};
607 std::vector<std::vector<int>> queries = {
608 {2, 6, 8}, {2, 3, 6}, {1, 3, 4}, {2, 7, 1}, {1, 5, 3},
609 {1, 7, 8}, {2, 6, 4}, {2, 7, 8}, {1, 1, 4}, {1, 2, 7}};
610 std::vector<int> expected_result = {34, 8, 16, 14, 10};
611 std::vector<int> code_result;
615 for (
int i = 0; i < n - 1; i++) {
616 int u = edges[i][0], v = edges[i][1];
620 for (
const auto &q : queries) {
623 int p = q[1], x = q[2];
625 }
else if (type == 2) {
626 int a = q[1], b = q[2];
627 code_result.push_back(hld.
query(a - 1, b - 1));
632 for (
int i = 0; i < static_cast<int>(expected_result.size()); i++) {
633 assert(expected_result[i] == code_result[i]);
635 std::cout <<
"\nTest3 passed!\n";
The Heavy-Light Decomposition class.
void dfs_labels(int u, int p=-1)
Utility function to lable the nodes so that heavy chains have a contigous lable.
std::vector< int > h_parent
stores the top of the heavy chain from a node
void dfs_par(int u, int p=-1)
Utility function to assign highest parent that can be reached though heavy chains.
X query(int a, int b)
This function returns the sum of node values in the simple path from from node_1 to node_2.
HLD(int nodes)
Class parameterized constructor. Resizes the and initilizes the data members.
int label
utility member to assign labels in dfs_labels()
X chain_query(int a, int b)
Utility function to break down a path query into two chain queries.
std::vector< int > h_heavychlid
stores the heavy child of a node
void update(int node, X val)
This function updates the value at node with val.
std::vector< int > h_label
stores the label of a node
void init()
This function must be called after the tree adjacency list and node values are populated The function...
void dfs_hc(int u, int p=-1)
Utility function to assign heavy child to each node (-1 for a leaf node)
X query(int l, int r)
Make a range query from node label l to node label r.
void update(int p, X v)
Update the value at a node.
X combine(X lhs, X rhs)
Function that specifies the type of operation involved when segments are combined.
X sret_init
inital query return value
int s_size
number of leaves in the segment tree
void set_sret_init(X new_sret_init)
Set the initialization for the query data type, based on requirement.
SG(int size)
Class parameterized constructor. Resizes the and initilizes the data members.
std::vector< X > s_tree
Everything here is private, and can only be accessed through the methods, in the derived class (HLD)
void set_node_val(const std::vector< X > &node_val)
Set the values for all the nodes.
std::vector< int > t_depth
a vector to store the depth of a node,
std::vector< X > t_val
values of nodes
std::vector< std::vector< int > > t_par
a matrix to store every node's 2^kth parent
void add_edge(const int u, const int v)
Adds an undirected edge from node u to node v in the tree.
Tree(int nodes)
Class parameterized constructor, resizes the and initializes the data members.
int kth_ancestor(int p, const int &dist)
The function returns the kth ancestor of a node.
void dfs_size(int u, int p=-1)
Utility function to compute sub-tree sizes.
int t_root
the root of the tree
std::vector< std::list< int > > t_adj
an adjacency list to stores the tree edges
const int t_maxlift
maximum possible height of the tree
void change_root(int new_root)
Set the root for the tree.
void lift(int *const p, int dist)
The function lifts a node, k units up the tree. The lifting is done in place, and the result is store...
void init()
This function must be called after the tree adjacency list and node values are populated The function...
std::vector< int > t_size
a vector to store the subtree size rooted at node
int lca(int a, int b)
The function returns the least common ancestor of two nodes.
const int t_nodes
number of nodes
void dfs_lca(int u, int p=-1)
Utility function to populate the t_par vector.
Heavy light decomposition algorithm.