forked from bicsi/code_snippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
segm_tree.cpp
64 lines (57 loc) · 1.42 KB
/
segm_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
template<typename T, typename Acc>
class SegmentTree {
size_t dim;
vector<T> data;
Acc acc;
void build(int node, const int &b, const int &e, const vector<T> &from) {
if(e == b + 1) {
data[node] = from[b];
} else {
int m = (b + e) / 2;
build(node * 2, b, m, from);
build(node * 2 + 1, m, e, from);
data[node] = acc(data[node * 2], data[node * 2 + 1]);
}
}
void update(int node, const int &b, const int &e, const int &pos, const T &x) {
if(e == b + 1) {
data[node] = x;
} else {
int m = (b + e) / 2;
pos < m
? update(node * 2, b, m, pos, x)
: update(node * 2 + 1, m, e, pos, x);
data[node] = acc(data[node * 2], data[node * 2 + 1]);
}
}
void query(int node, const int &b, const int &e, const int &l, const int &r) {
if(b >= l && e <= r) {
data[0] = b == l
? data[node]
: acc(data[0], data[node]);
return;
}
int m = (b + e) / 2;
if(l < m) query(node * 2, b, m, l, r);
if(r > m) query(node * 2 + 1, m, e, l, r);
}
public:
SegmentTree(size_t dim, Acc acc = Acc()) :
dim(dim), data(dim * 4), acc(acc) {}
SegmentTree(const vector<T> &from, Acc acc = Acc()) :
dim(from.size()), data(from.size() * 4), acc(acc)
{
build(1, 0, dim, from);
}
void Set(int pos, T value) {
update(1, 0, dim, pos, value);
}
T Get(int pos) {
return QueryRange(pos, pos + 1);
}
T QueryRange(int b, int e) {
assert(b < e);
query(1, 0, dim, b, e);
return data[0];
}
};