-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
fenwick_tree.cpp
135 lines (124 loc) · 3.91 KB
/
fenwick_tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* @file
* @brief [Fenwick Tree](https://en.wikipedia.org/wiki/Fenwick_tree) algorithm
* implementation
* @details
* _From Wikipedia, the free encyclopedia._
*
* A Fenwick tree or binary indexed tree (BIT) is a clever implementation of a
* datastructure called bionomal tree. It can update values and solve range
* queries with operations that is; commulative, associative and has an
* inverse for this type of element. It can also solve immutable range queries
* (min/max), when operations only are associative over this type of element.
* Some of these restrictions can be removed, by storing redunant information;
* like in max/min range queries.
*
* @author [Mateusz Grzegorzek](https://github.com/mateusz-grzegorzek)
* @author [David Leal](https://github.com/Panquesito7)
*/
#include <cassert> /// for assert
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @namespace
* @brief Range Queries
*/
namespace range_queries {
/**
* @brief The class that initializes the Fenwick Tree.
*/
class fenwick_tree {
size_t n = 0; ///< No. of elements present in input array
std::vector<int> bit{}; ///< Array that represents Binary Indexed Tree.
/**
* @brief Returns the highest power of two which is not more than `x`.
* @param x Index of element in original array.
* @return Offset of index.
*/
inline int offset(int x) { return (x & (-x)); }
public:
/**
* @brief Class Constructor
* @tparam T the type of the array
* @param[in] arr Input array for which prefix sum is evaluated.
* @return void
*/
template <typename T>
explicit fenwick_tree(const std::vector<T>& arr) : n(arr.size()) {
bit.assign(n + 1, 0);
for (int i = 0; i < n; ++i) {
update(i, arr[i]);
}
}
/**
* @brief Class Constructor
* @tparam T the type of the variable
* @param[in] x Size of array that represents Binary Indexed Tree.
* @return void
*/
template <typename T>
explicit fenwick_tree(T x) : n(x) { bit.assign(n + 1, 0); }
/**
* @brief Updates the value of an element in original array and
* accordingly updates the values in BIT array.
* @tparam T the type of the variables
* @param id Index of element in original array.
* @param val Value with which element's value is updated.
* @return void
*/
template <typename T>
void update(T id, T val) {
id++;
while (id <= n) {
bit[id] += val;
id += offset(id);
}
}
/**
* @brief Returns the sum of elements in range from 0 to ID.
* @tparam T the type of the variables
* @param id Index in original array up to which sum is evaluated.
* @return Sum of elements in range from 0 to id.
*/
template <typename T>
int sum(T id) {
id++;
T res = 0;
while (id > 0) {
res += bit[id];
id -= offset(id);
}
return res;
}
/**
* @brief Returns the prefix sum in range from L to R.
* @param l Left index of range.
* @param r Right index of range.
* @return Sum of elements in range from L to R.
*/
int sum_range(int l, int r) { return sum(r) - sum(l - 1); }
};
} // namespace range_queries
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
std::vector<int> arr = {1, 2, 3, 4, 5};
range_queries::fenwick_tree fenwick_tree(arr);
assert(fenwick_tree.sum_range(0, 0) == 1);
assert(fenwick_tree.sum_range(0, 1) == 3);
assert(fenwick_tree.sum_range(0, 2) == 6);
assert(fenwick_tree.sum_range(0, 3) == 10);
assert(fenwick_tree.sum_range(0, 4) == 15);
fenwick_tree.update(0, 6);
std::cout << "All tests have successfully passed!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // run self-test implementations
return 0;
}