TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
segtree.cpp File Reference

Implementation of [Segment Tree] (https://en.wikipedia.org/wiki/Segment_tree) data structure. More...

#include <cassert>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <vector>
Include dependency graph for segtree.cpp:

Go to the source code of this file.

Functions

void ConsTree (const std::vector< int64_t > &arr, std::vector< int64_t > *segtree, uint64_t low, uint64_t high, uint64_t pos)
 for std::vector
 
int64_t query (std::vector< int64_t > *segtree, std::vector< int64_t > *lazy, uint64_t qlow, uint64_t qhigh, uint64_t low, uint64_t high, uint64_t pos)
 Returns the sum of all elements in a range.
 
void update (std::vector< int64_t > *segtree, std::vector< int64_t > *lazy, int64_t start, int64_t end, int64_t delta, uint64_t low, uint64_t high, uint64_t pos)
 Updates a range of the segment tree.
 
static void test ()
 Self-test implementation.
 
int main ()
 Main function.
 

Detailed Description

Implementation of [Segment Tree] (https://en.wikipedia.org/wiki/Segment_tree) data structure.

A segment tree, also known as a statistic tree, is a tree data structure used for storing information about intervals, or segments. Its classical version allows querying which of the stored segments contain a given point, but our modification allows us to perform (query) any binary operation on any range in the array in O(logN) time. Here, we have used addition (+). For range updates, we have used lazy propagation.

  • Space Complexity : O(NlogN)
  • Build Time Complexity : O(NlogN)
  • Query Time Complexity : O(logN)
    Author
    Madhav Gaba
    Soham Roy

Definition in file segtree.cpp.

Function Documentation

◆ ConsTree()

void ConsTree ( const std::vector< int64_t > & arr,
std::vector< int64_t > * segtree,
uint64_t low,
uint64_t high,
uint64_t pos )

for std::vector

for assert for log2 for std::uint64_t for IO operations

Constructs the initial segment tree

Parameters
arrinput to construct the tree out of
segtreethe segment tree
lowinclusive lowest index of arr to begin at
highinclusive highest index of arr to end at
posindex of segtree to fill (eg. root node)
Returns
void

Definition at line 38 of file segtree.cpp.

39 {
40 if (low == high) {
41 (*segtree)[pos] = arr[low];
42 return;
43 }
44
45 uint64_t mid = (low + high) / 2;
46 ConsTree(arr, segtree, low, mid, 2 * pos + 1);
47 ConsTree(arr, segtree, mid + 1, high, 2 * pos + 2);
48 (*segtree)[pos] = (*segtree)[2 * pos + 1] + (*segtree)[2 * pos + 2];
49}
void ConsTree(const std::vector< int64_t > &arr, std::vector< int64_t > *segtree, uint64_t low, uint64_t high, uint64_t pos)
for std::vector
Definition segtree.cpp:38

◆ main()

int main ( void )

Main function.

Returns
0 on exit

Definition at line 168 of file segtree.cpp.

168 {
169 test(); // run self-test implementations
170
171 std::cout << "Enter number of elements: ";
172
173 uint64_t n = 0;
174 std::cin >> n;
175
176 auto max = static_cast<uint64_t>(2 * pow(2, ceil(log2(n))) - 1);
177 std::vector<int64_t> arr(n), lazy(max), segtree(max);
178
179 int choice = 0;
180 std::cout << "\nDo you wish to enter each number?:\n"
181 "1: Yes\n"
182 "0: No (default initialize them to 0)\n";
183
184 std::cin >> choice;
185 if (choice == 1) {
186 std::cout << "Enter " << n << " numbers:\n";
187 for (int i = 1; i <= n; i++) {
188 std::cout << i << ": ";
189 std::cin >> arr[i];
190 }
191 }
192
193 ConsTree(arr, &segtree, 0, n - 1, 0);
194
195 do {
196 std::cout << "\nMake your choice:\n"
197 "1: Range update (input)\n"
198 "2: Range query (output)\n"
199 "0: Exit\n";
200 std::cin >> choice;
201
202 if (choice == 1) {
203 std::cout << "Enter 1-indexed lower bound, upper bound & value:\n";
204
205 uint64_t p = 1, q = 1, v = 0;
206 std::cin >> p >> q >> v;
207 update(&segtree, &lazy, p - 1, q - 1, v, 0, n - 1, 0);
208 } else if (choice == 2) {
209 std::cout << "Enter 1-indexed lower bound & upper bound:\n";
210
211 uint64_t p = 1, q = 1;
212 std::cin >> p >> q;
213 std::cout << query(&segtree, &lazy, p - 1, q - 1, 0, n - 1, 0);
214 std::cout << "\n";
215 }
216 } while (choice > 0);
217
218 return 0;
219}
int64_t query(std::vector< int64_t > *segtree, std::vector< int64_t > *lazy, uint64_t qlow, uint64_t qhigh, uint64_t low, uint64_t high, uint64_t pos)
Returns the sum of all elements in a range.
Definition segtree.cpp:63
static void test()
Self-test implementation.
Definition segtree.cpp:147
void update(std::vector< int64_t > *segtree, std::vector< int64_t > *lazy, int64_t start, int64_t end, int64_t delta, uint64_t low, uint64_t high, uint64_t pos)
Updates a range of the segment tree.
Definition segtree.cpp:103

◆ query()

int64_t query ( std::vector< int64_t > * segtree,
std::vector< int64_t > * lazy,
uint64_t qlow,
uint64_t qhigh,
uint64_t low,
uint64_t high,
uint64_t pos )

Returns the sum of all elements in a range.

Parameters
segtreethe segment tree
lazyfor lazy propagation
qlowlower index of the required query
qhighhigher index of the required query
lowlower index of query for this function call
highhigher index of query for this function call
posindex of segtree to consider (eg. root node)
Returns
result of the range query for this function call

Definition at line 63 of file segtree.cpp.

65 {
66 if (low > high || qlow > high || low > qhigh) {
67 return 0;
68 }
69
70 if ((*lazy)[pos] != 0) {
71 (*segtree)[pos] += (*lazy)[pos] * (high - low + 1);
72
73 if (low != high) {
74 (*lazy)[2 * pos + 1] += (*lazy)[pos];
75 (*lazy)[2 * pos + 2] += (*lazy)[pos];
76 }
77 (*lazy)[pos] = 0;
78 }
79
80 if (qlow <= low && qhigh >= high) {
81 return (*segtree)[pos];
82 }
83
84 uint64_t mid = (low + high) / 2;
85
86 return query(segtree, lazy, qlow, qhigh, low, mid, 2 * pos + 1) +
87 query(segtree, lazy, qlow, qhigh, mid + 1, high, 2 * pos + 2);
88}

◆ test()

static void test ( )
static

Self-test implementation.

Returns
void

Definition at line 147 of file segtree.cpp.

147 {
148 auto max = static_cast<int64_t>(2 * pow(2, ceil(log2(7))) - 1);
149 assert(max == 15);
150
151 std::vector<int64_t> arr{1, 2, 3, 4, 5, 6, 7}, lazy(max), segtree(max);
152 ConsTree(arr, &segtree, 0, 7 - 1, 0);
153
154 assert(query(&segtree, &lazy, 1, 5, 0, 7 - 1, 0) == 2 + 3 + 4 + 5 + 6);
155
156 update(&segtree, &lazy, 2, 4, 1, 0, 7 - 1, 0);
157 assert(query(&segtree, &lazy, 1, 5, 0, 7 - 1, 0) == 2 + 4 + 5 + 6 + 6);
158
159 update(&segtree, &lazy, 0, 6, -2, 0, 7 - 1, 0);
160 assert(query(&segtree, &lazy, 0, 4, 0, 7 - 1, 0) == -1 + 0 + 2 + 3 + 4);
161}

◆ update()

void update ( std::vector< int64_t > * segtree,
std::vector< int64_t > * lazy,
int64_t start,
int64_t end,
int64_t delta,
uint64_t low,
uint64_t high,
uint64_t pos )

Updates a range of the segment tree.

Parameters
segtreethe segment tree
lazyfor lazy propagation
startlower index of the required query
endhigher index of the required query
deltainteger to add to each element of the range
lowlower index of query for this function call
highhigher index of query for this function call
posindex of segtree to consider (eg. root node)
Returns
void

Definition at line 103 of file segtree.cpp.

105 {
106 if (low > high) {
107 return;
108 }
109
110 if ((*lazy)[pos] != 0) {
111 (*segtree)[pos] += (*lazy)[pos] * (high - low + 1);
112
113 if (low != high) {
114 (*lazy)[2 * pos + 1] += (*lazy)[pos];
115 (*lazy)[2 * pos + 2] += (*lazy)[pos];
116 }
117 (*lazy)[pos] = 0;
118 }
119
120 if (start > high || end < low) {
121 return;
122 }
123
124 if (start <= low && end >= high) {
125 (*segtree)[pos] += delta * (high - low + 1);
126
127 if (low != high) {
128 (*lazy)[2 * pos + 1] += delta;
129 (*lazy)[2 * pos + 2] += delta;
130 }
131
132 return;
133 }
134
135 uint64_t mid = (low + high) / 2;
136
137 update(segtree, lazy, start, end, delta, low, mid, 2 * pos + 1);
138 update(segtree, lazy, start, end, delta, mid + 1, high, 2 * pos + 2);
139 (*segtree)[pos] = (*segtree)[2 * pos + 1] + (*segtree)[2 * pos + 2];
140}