-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathbinary_indexed_tree.cpp
59 lines (49 loc) · 1.62 KB
/
binary_indexed_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
#include <iterator>
#include <vector>
#include <cassert>
#include <functional>
template<typename T, typename AssociativeOperation>
struct binary_indexed_tree {
int SZ;
T identity;
AssociativeOperation TT;
std::vector<T> data;
binary_indexed_tree() {}
binary_indexed_tree(int _SZ, T _identity, AssociativeOperation _TT)
: SZ(_SZ), identity(_identity), TT(_TT) {
data.assign(2 * SZ, identity);
}
// Replaces the current value at index i with TT(current value, v)
void add(int i, T v) {
for (i++; i <= SZ; i += i & -i)
data[i] = TT(data[i], v);
}
// Returns the result of accumulating the elements at indices in [0, len)
T accumulate_prefix(int len) const {
assert(0 <= len && len <= SZ);
T res = identity;
for (; len; len -= len & -len)
res = TT(res, data[len]);
return res;
}
/* Returns the smallest len in [0, S] such that p(accumulate_prefix(len)) returns true.
* Returns S + 1 if no such len exists.
* Requires that p(accumulate_prefix(len)) is non-decreasing in len.
*/
template<typename Predicate>
int binary_search(Predicate p) const {
if (p(identity)) return 0;
int len = 0;
T accumulator = identity;
for (int bit = 31 - __builtin_clz(SZ); bit >= 0; bit--) {
int next = len + (1 << bit);
if (next > SZ) continue;
T combined = TT(accumulator, data[next]);
if (!p(combined)) {
len = next;
accumulator = combined;
}
}
return len + 1;
}
};