Algorithms_in_C++  1.0.0
Set of algorithms implemented in C++.
persistent_seg_tree_lazy_prop.cpp File Reference

Persistent segment tree with range updates (lazy propagation) More...

#include <iostream>
#include <memory>
#include <vector>
Include dependency graph for persistent_seg_tree_lazy_prop.cpp:

Classes

class  range_queries::perSegTree
 Range query here is range sum, but the code can be modified to make different queries like range max or min. More...
 
class  range_queries::perSegTree::Node
 

Namespaces

 range_queries
 Algorithms and Data Structures that support range queries and updates.
 

Functions

static void test ()
 Test implementations. More...
 
int main ()
 Main function. More...
 

Detailed Description

Persistent segment tree with range updates (lazy propagation)

A normal segment tree facilitates making point updates and range queries in logarithmic time. Lazy propagation preserves the logarithmic time with range updates. So, a segment tree with lazy propagation enables doing range updates and range queries in logarithmic time, but it doesn't save any information about itself before the last update. A persistent data structure always preserves the previous version of itself when it is modified. That is, a new version of the segment tree is generated after every update. It saves all previous versions of itself (before every update) to facilitate doing range queries in any version. More memory is used ,but the logarithmic time is preserved because the new version points to the same nodes, that the previous version points to, that are not affected by the update. That is, only the nodes that are affected by the update and their ancestors are copied. The rest is copied using lazy propagation in the next queries. Thus preserving the logarithmic time because the number of nodes copied after any update is logarithmic.

Author
Magdy Sedra

Function Documentation

◆ main()

int main ( void  )

Main function.

Returns
0 on exit
318  {
319  test(); // run self-test implementations
320  return 0;
321 }
static void test()
Test implementations.
Definition: persistent_seg_tree_lazy_prop.cpp:268
Here is the call graph for this function:

◆ test()

static void test ( )
static

Test implementations.

Returns
void
268  {
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) {
273  std::cout << arr[i];
274  if (i != arr.size() - 1) {
275  std::cout << ",";
276  }
277  }
278  std::cout << "}\n";
279  tree.construct(
280  arr); // constructing the original segment tree (version = 0)
281  std::cout << "Querying range sum on version 0 from index 2 to 4 = 3+11-2 = "
282  << tree.query(2, 4, 0) << '\n';
283  std::cout
284  << "Subtract 7 from all elements from index 1 to index 5 inclusive\n";
285  tree.update(1, 5, -7); // subtracting 7 from index 1 to index 5
286  std::cout << "Elements of the segment tree whose version = 1 (after 1 "
287  "update) are {";
288  for (uint32_t i = 0; i < arr.size(); ++i) {
289  std::cout << tree.query(i, i, 1);
290  if (i != arr.size() - 1) {
291  std::cout << ",";
292  }
293  }
294  std::cout << "}\n";
295  std::cout << "Add 10 to all elements from index 0 to index 7 inclusive\n";
296  tree.update(0, 7, 10); // adding 10 to all elements
297  std::cout << "Elements of the segment tree whose version = 2 (after 2 "
298  "updates) are {";
299  for (uint32_t i = 0; i < arr.size(); ++i) {
300  std::cout << tree.query(i, i, 2);
301  if (i != arr.size() - 1) {
302  std::cout << ",";
303  }
304  }
305  std::cout << "}\n";
306  std::cout << "Number of segment trees (versions) now = " << tree.size()
307  << '\n';
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';
312 }
Range query here is range sum, but the code can be modified to make different queries like range max ...
Definition: persistent_seg_tree_lazy_prop.cpp:39
uint32_t size()
Getting the number of versions after updates so far which is equal to the size of the pointers vector...
Definition: persistent_seg_tree_lazy_prop.cpp:255
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...
Definition: persistent_seg_tree_lazy_prop.cpp:106
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...
Definition: persistent_seg_tree_lazy_prop.cpp:171
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 ...
Definition: persistent_seg_tree_lazy_prop.cpp:135
T size(T... args)
Here is the call graph for this function: