43 std::shared_ptr<Node> left =
nullptr;
44 std::shared_ptr<Node>
right =
nullptr;
53 std::vector<std::shared_ptr<Node>>
57 std::vector<int64_t>
vec{};
65 std::shared_ptr<Node>
newKid(std::shared_ptr<Node>
const &curr) {
66 auto newNode = std::make_shared<Node>(
Node());
67 newNode->left = curr->left;
68 newNode->right = curr->right;
69 newNode->prop = curr->prop;
70 newNode->val = curr->val;
83 void lazy(
const uint32_t &i,
const uint32_t &j,
84 std::shared_ptr<Node>
const &curr) {
88 curr->val += (j - i + 1) * curr->prop;
90 curr->left =
newKid(curr->left);
91 curr->right =
newKid(curr->right);
92 curr->left->prop += curr->prop;
93 curr->right->prop += curr->prop;
106 std::shared_ptr<Node>
construct(
const uint32_t &i,
const uint32_t &j) {
107 auto newNode = std::make_shared<Node>(
Node());
109 newNode->val =
vec[i];
111 uint32_t mid = i + (j - i) / 2;
114 newNode->val = leftt->val + right->val;
115 newNode->left = leftt;
116 newNode->right = right;
135 std::shared_ptr<Node>
update(
const uint32_t &i,
const uint32_t &j,
136 const uint32_t &l,
const uint32_t &r,
137 const int64_t &value,
138 std::shared_ptr<Node>
const &curr) {
140 if (i >= l && j <= r) {
141 std::shared_ptr<Node> newNode =
newKid(curr);
142 newNode->prop += value;
146 if (i > r || j < l) {
149 auto newNode = std::make_shared<Node>(
Node());
150 uint32_t mid = i + (j - i) / 2;
151 newNode->left =
update(i, mid, l, r, value, curr->left);
152 newNode->right =
update(mid + 1, j, l, r, value, curr->right);
153 newNode->val = newNode->left->val + newNode->right->val;
171 int64_t
query(
const uint32_t &i,
const uint32_t &j,
const uint32_t &l,
172 const uint32_t &r, std::shared_ptr<Node>
const &curr) {
174 if (j < l || r < i) {
177 if (i >= l && j <= r) {
180 uint32_t mid = i + (j - i) / 2;
181 return query(i, mid, l, r, curr->left) +
182 query(mid + 1, j, l, r, curr->right);
207 ptrs.push_back(root);
219 void update(
const uint32_t &l,
const uint32_t &r,
225 0, n - 1, l, r, value,
242 const uint32_t &l,
const uint32_t &r,
247 return query(0, n - 1, l, r,
ptrs[version]);
269 std::vector<int64_t> arr = {-5, 2, 3, 11, -2, 7, 0, 1};
271 std::cout <<
"Elements before any updates are {";
272 for (uint32_t i = 0; i < arr.size(); ++i) {
274 if (i != arr.size() - 1) {
281 std::cout <<
"Querying range sum on version 0 from index 2 to 4 = 3+11-2 = "
282 << tree.
query(2, 4, 0) <<
'\n';
284 <<
"Subtract 7 from all elements from index 1 to index 5 inclusive\n";
286 std::cout <<
"Elements of the segment tree whose version = 1 (after 1 "
288 for (uint32_t i = 0; i < arr.size(); ++i) {
289 std::cout << tree.
query(i, i, 1);
290 if (i != arr.size() - 1) {
295 std::cout <<
"Add 10 to all elements from index 0 to index 7 inclusive\n";
297 std::cout <<
"Elements of the segment tree whose version = 2 (after 2 "
299 for (uint32_t i = 0; i < arr.size(); ++i) {
300 std::cout << tree.
query(i, i, 2);
301 if (i != arr.size() - 1) {
306 std::cout <<
"Number of segment trees (versions) now = " << tree.
size()
308 std::cout <<
"Querying range sum on version 0 from index 3 to 5 = 11-2+7 = "
309 << tree.
query(3, 5, 0) <<
'\n';
310 std::cout <<
"Querying range sum on version 1 from index 3 to 5 = 4-9+0 = "
311 << tree.
query(3, 5, 1) <<
'\n';
std::shared_ptr< Node > right
pointer to the left node
int64_t val
pointer to the right node
Range query here is range sum, but the code can be modified to make different queries like range max ...
std::shared_ptr< Node > newKid(std::shared_ptr< Node > const &curr)
Creating a new node with the same values of curr node.
uint32_t size()
Getting the number of versions after updates so far which is equal to the size of the pointers vector...
std::vector< std::shared_ptr< Node > > ptrs
number of elements/leaf nodes in the segment tree
std::shared_ptr< Node > update(const uint32_t &i, const uint32_t &j, const uint32_t &l, const uint32_t &r, const int64_t &value, std::shared_ptr< Node > const &curr)
Doing range update, checking at every node if it has some value to be propagated. All nodes affected ...
std::shared_ptr< Node > construct(const uint32_t &i, const uint32_t &j)
Constructing the segment tree with the early passed vector. Every call creates a node to hold the sum...
std::vector< int64_t > vec
void construct(const std::vector< int64_t > &vec)
Constructing the segment tree with the values in the passed vector. Returned root pointer is pushed i...
void lazy(const uint32_t &i, const uint32_t &j, std::shared_ptr< Node > const &curr)
If there is some value to be propagated to the passed node, value is added to the node and the childr...
int64_t query(const uint32_t &l, const uint32_t &r, const uint32_t &version)
Querying the range from index l to index r, getting the sum of the elements whose index x satisfies l...
int64_t query(const uint32_t &i, const uint32_t &j, const uint32_t &l, const uint32_t &r, std::shared_ptr< Node > const &curr)
Querying the range from index l to index r, checking at every node if it has some value to be propaga...
void update(const uint32_t &l, const uint32_t &r, const int64_t &value)
Doing range update by passing the left and right indexes of the range as well as the value to be adde...
static void test()
Test implementations.