-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathrmq_segment_tree.hpp
150 lines (121 loc) · 4.05 KB
/
rmq_segment_tree.hpp
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <iostream>
#include <vector>
#include <cmath>
#include <cassert>
#define LEFT(i) 2 * i + 1
#define RIGHT(i) 2 * i + 2
#define PARENT(i) (i - 1) / 2
template<typename IntType, typename BinaryFunct>
struct rmq_segment_tree {
struct type_traits {
IntType invalid;
BinaryFunct funct;
};
struct builder {
builder()
{}
builder(std::vector<IntType> const& leaves, type_traits traits)
: m_traits(traits)
{
size_t n = leaves.size();
// round up to the next power of 2
size_t m = size_t(1) << static_cast<size_t>(ceil(log2(n)));
m_tree.resize(2 * m - 1, m_traits.invalid);
build(leaves, 0, n - 1, 0);
// for (auto x: m_tree) {
// std::cout << x << " ";
// } std::cout << std::endl;
}
void swap(builder& other) {
std::swap(other.m_traits, m_traits);
other.m_tree.swap(m_tree);
}
void build(rmq_segment_tree& rst) {
std::swap(rst.m_traits, m_traits);
rst.m_tree.swap(m_tree);
builder().swap(*this);
}
private:
type_traits m_traits;
std::vector<IntType> m_tree;
void build(std::vector<IntType> const& leaves, size_t lo, size_t hi, size_t pos) {
if (lo == hi) {
m_tree[pos] = leaves[lo];
return;
}
size_t mid = (lo + hi) / 2;
build(leaves, lo, mid, LEFT(pos));
build(leaves, mid + 1, hi, RIGHT(pos));
m_tree[pos] = m_traits.funct(m_tree[LEFT(pos)], m_tree[RIGHT(pos)]);
}
};
rmq_segment_tree()
{}
// debug purposes
void print_tree() const {
for (auto x: m_tree) {
std::cout << x << " ";
} std::cout << std::endl;
}
struct range {
range(size_t l, size_t h)
: lo(l), hi(h)
{}
size_t lo, hi;
};
range root() const {
return range(0, size() - 1);
}
size_t size() const {
return m_tree.size() / 2 + 1;
}
IntType rmq(range const& query, range node_segment, size_t pos) {
if (query.lo <= node_segment.lo
and query.hi >= node_segment.hi) { // total overlap
return m_tree[pos];
}
if (query.lo > node_segment.hi
or query.hi < node_segment.lo) { // no overlap
return m_traits.invalid;
}
// partial overlap
size_t mid = (node_segment.lo + node_segment.hi) / 2;
return m_traits.funct(
rmq(query, {node_segment.lo, mid}, LEFT(pos)),
rmq(query, {mid + 1, node_segment.hi}, RIGHT(pos))
);
}
// increment the i-th leaf by delta
void update(size_t i, IntType delta, range node_segment, size_t pos) {
if (i > node_segment.hi
or i < node_segment.lo) {
return;
}
if (node_segment.lo == node_segment.hi) { // leaf
m_tree[pos] += delta;
return;
}
size_t mid = (node_segment.lo + node_segment.hi) / 2;
update(i, delta, {node_segment.lo, mid}, LEFT(pos));
update(i, delta, {mid + 1, node_segment.hi}, RIGHT(pos));
m_tree[pos] = m_traits.funct(m_tree[LEFT(pos)], m_tree[RIGHT(pos)]);
}
// increment all leaves in the range [query.lo, query.hi] by delta
void update_range(range const& query, IntType delta, range node_segment, size_t pos) {
if (query.lo > node_segment.hi
or query.hi < node_segment.lo) {
return;
}
if (node_segment.lo == node_segment.hi) { // leaf
m_tree[pos] += delta;
return;
}
size_t mid = (node_segment.lo + node_segment.hi) / 2;
update_range(query, delta, {node_segment.lo, mid}, LEFT(pos));
update_range(query, delta, {mid + 1, node_segment.hi}, RIGHT(pos));
m_tree[pos] = m_traits.funct(m_tree[LEFT(pos)], m_tree[RIGHT(pos)]);
}
private:
type_traits m_traits;
std::vector<IntType> m_tree;
};