44 std::shared_ptr<Node> left =
nullptr;
45 std::shared_ptr<Node>
right =
nullptr;
54 std::vector<std::shared_ptr<Node>>
58 std::vector<int64_t>
vec{};
66 std::shared_ptr<Node>
newKid(std::shared_ptr<Node>
const &curr) {
67 auto newNode = std::make_shared<Node>(
Node());
68 newNode->left = curr->left;
69 newNode->right = curr->right;
70 newNode->prop = curr->prop;
71 newNode->val = curr->val;
84 void lazy(
const uint32_t &i,
const uint32_t &j,
85 std::shared_ptr<Node>
const &curr) {
89 curr->val += (j - i + 1) * curr->prop;
91 curr->left =
newKid(curr->left);
92 curr->right =
newKid(curr->right);
93 curr->left->prop += curr->prop;
94 curr->right->prop += curr->prop;
107 std::shared_ptr<Node>
construct(
const uint32_t &i,
const uint32_t &j) {
108 auto newNode = std::make_shared<Node>(
Node());
110 newNode->val =
vec[i];
112 uint32_t mid = i + (j - i) / 2;
115 newNode->val = leftt->val + right->val;
116 newNode->left = leftt;
117 newNode->right = right;
136 std::shared_ptr<Node>
update(
const uint32_t &i,
const uint32_t &j,
137 const uint32_t &l,
const uint32_t &r,
138 const int64_t &value,
139 std::shared_ptr<Node>
const &curr) {
141 if (i >= l && j <= r) {
142 std::shared_ptr<Node> newNode =
newKid(curr);
143 newNode->prop += value;
147 if (i > r || j < l) {
150 auto newNode = std::make_shared<Node>(
Node());
151 uint32_t mid = i + (j - i) / 2;
152 newNode->left =
update(i, mid, l, r, value, curr->left);
153 newNode->right =
update(mid + 1, j, l, r, value, curr->right);
154 newNode->val = newNode->left->val + newNode->right->val;
172 int64_t
query(
const uint32_t &i,
const uint32_t &j,
const uint32_t &l,
173 const uint32_t &r, std::shared_ptr<Node>
const &curr) {
175 if (j < l || r < i) {
178 if (i >= l && j <= r) {
181 uint32_t mid = i + (j - i) / 2;
182 return query(i, mid, l, r, curr->left) +
183 query(mid + 1, j, l, r, curr->right);
208 ptrs.push_back(root);
220 void update(
const uint32_t &l,
const uint32_t &r,
226 0, n - 1, l, r, value,
243 const uint32_t &l,
const uint32_t &r,
248 return query(0, n - 1, l, r,
ptrs[version]);
270 std::vector<int64_t> arr = {-5, 2, 3, 11, -2, 7, 0, 1};
272 std::cout <<
"Elements before any updates are {";
273 for (uint32_t i = 0; i < arr.size(); ++i) {
275 if (i != arr.size() - 1) {
282 std::cout <<
"Querying range sum on version 0 from index 2 to 4 = 3+11-2 = "
283 << tree.
query(2, 4, 0) <<
'\n';
285 <<
"Subtract 7 from all elements from index 1 to index 5 inclusive\n";
287 std::cout <<
"Elements of the segment tree whose version = 1 (after 1 "
289 for (uint32_t i = 0; i < arr.size(); ++i) {
290 std::cout << tree.
query(i, i, 1);
291 if (i != arr.size() - 1) {
296 std::cout <<
"Add 10 to all elements from index 0 to index 7 inclusive\n";
298 std::cout <<
"Elements of the segment tree whose version = 2 (after 2 "
300 for (uint32_t i = 0; i < arr.size(); ++i) {
301 std::cout << tree.
query(i, i, 2);
302 if (i != arr.size() - 1) {
307 std::cout <<
"Number of segment trees (versions) now = " << tree.
size()
309 std::cout <<
"Querying range sum on version 0 from index 3 to 5 = 11-2+7 = "
310 << tree.
query(3, 5, 0) <<
'\n';
311 std::cout <<
"Querying range sum on version 1 from index 3 to 5 = 4-9+0 = "
312 << 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.