TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
segtree.cpp
Go to the documentation of this file.
1
22#include <cassert>
23#include <cmath>
24#include <cstdint>
25#include <iostream>
26#include <vector>
27
38void ConsTree(const std::vector<int64_t> &arr, std::vector<int64_t> *segtree,
39 uint64_t low, uint64_t high, uint64_t pos) {
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}
50
63int64_t query(std::vector<int64_t> *segtree, std::vector<int64_t> *lazy,
64 uint64_t qlow, uint64_t qhigh, uint64_t low, uint64_t high,
65 uint64_t pos) {
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}
89
103void update(std::vector<int64_t> *segtree, std::vector<int64_t> *lazy,
104 int64_t start, int64_t end, int64_t delta, uint64_t low,
105 uint64_t high, uint64_t pos) {
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}
141
147static void test() {
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}
162
168int main() {
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
int main()
Main function.
Definition segtree.cpp:168
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