Pixie
Loading...
Searching...
No Matches
naive_rmm_tree.h
1#pragma once
2#include <algorithm>
3#include <cstdint>
4#include <limits>
5#include <string>
6#include <vector>
7
8class NaiveRmM {
9 std::vector<uint8_t> bits;
10 std::size_t num_bits = 0;
11
12 public:
13 static constexpr std::size_t npos = std::numeric_limits<std::size_t>::max();
14
15 NaiveRmM() = default;
16 explicit NaiveRmM(const std::string& s) { build_from_string(s); }
17 NaiveRmM(const std::vector<std::uint64_t>& words, std::size_t nbits) {
18 build_from_words(words, nbits);
19 }
20
21 private:
22 void build_from_string(const std::string& s) {
23 num_bits = s.size();
24 bits.resize(num_bits);
25 for (std::size_t i = 0; i < num_bits; i++) {
26 bits[i] = (s[i] == '1');
27 }
28 }
29 void build_from_words(const std::vector<std::uint64_t>& words,
30 std::size_t nbits) {
31 num_bits = nbits;
32 bits.assign(num_bits, 0);
33 for (std::size_t i = 0; i < num_bits; i++) {
34 const std::size_t w = (i >> 6);
35 bits[i] = static_cast<uint8_t>(
36 ((w < words.size() ? words[w] : 0ull) >> (i & 63)) & 1u);
37 }
38 }
39
40 inline int bit(std::size_t i) const { return bits[i]; }
41
42 public:
43 std::size_t rank1(std::size_t i) const {
44 if (i > num_bits) {
45 i = num_bits;
46 }
47 std::size_t c = 0;
48 for (std::size_t p = 0; p < i; p++) {
49 c += (bits[p] != 0);
50 }
51 return c;
52 }
53 std::size_t rank0(std::size_t i) const { return i - rank1(i); }
54
55 // 1-based
56 std::size_t select1(std::size_t k) const {
57 if (k == 0) {
58 return npos;
59 }
60 for (std::size_t p = 0; p < num_bits; p++) {
61 if (bits[p]) {
62 if (--k == 0) {
63 return p;
64 }
65 }
66 }
67 return npos;
68 }
69
70 // 1-based
71 std::size_t select0(std::size_t k) const {
72 if (k == 0) {
73 return npos;
74 }
75 for (std::size_t p = 0; p < num_bits; p++) {
76 if (!bits[p]) {
77 if (--k == 0) {
78 return p;
79 }
80 }
81 }
82 return npos;
83 }
84
85 std::size_t rank10(std::size_t i) const {
86 if (i <= 1) {
87 return 0;
88 }
89 std::size_t c = 0;
90 for (std::size_t p = 0; p + 1 < i; ++p) {
91 if (bits[p] == 1 && bits[p + 1] == 0) {
92 ++c;
93 }
94 }
95 return c;
96 }
97
98 // 1-based
99 std::size_t select10(std::size_t k) const {
100 if (k == 0) {
101 return npos;
102 }
103 for (std::size_t p = 0; p + 1 < num_bits; ++p) {
104 if (bits[p] == 1 && bits[p + 1] == 0) {
105 if (--k == 0) {
106 return p;
107 }
108 }
109 }
110 return npos;
111 }
112
113 int excess(std::size_t i) const {
114 return int(2 * static_cast<long long>(rank1(i)) -
115 static_cast<long long>(i));
116 }
117
118 std::size_t fwdsearch(std::size_t i, int d) const {
119 if (i >= num_bits) {
120 return npos;
121 }
122 int target = excess(i) + d;
123 int cur = excess(i);
124 for (std::size_t p = i; p < num_bits; ++p) {
125 cur += bits[p] ? +1 : -1;
126 if (cur == target) {
127 return p;
128 }
129 }
130 return npos;
131 }
132
133 std::size_t bwdsearch(std::size_t i, int d) const {
134 if (i > num_bits) {
135 return npos;
136 }
137 if (i == 0) {
138 return npos;
139 }
140 int target = excess(i) + d;
141
142 int cur = excess(i);
143 for (std::size_t p = i; p > 0;) {
144 --p;
145 cur += bits[p] ? -1 : +1;
146 if (cur == target) {
147 return p;
148 }
149 }
150 return npos;
151 }
152
153 std::size_t range_min_query_pos(std::size_t i, std::size_t j) const {
154 if (i > j || j >= num_bits) {
155 return npos;
156 }
157 int cur = 0, mn = std::numeric_limits<int>::max();
158 std::size_t pos = npos;
159 for (std::size_t p = i; p <= j; ++p) {
160 cur += bits[p] ? +1 : -1;
161 if (cur < mn) {
162 mn = cur;
163 pos = p;
164 }
165 }
166 return pos;
167 }
168
169 int range_min_query_val(std::size_t i, std::size_t j) const {
170 if (i > j || j >= num_bits) {
171 return 0;
172 }
173 int cur = 0, mn = std::numeric_limits<int>::max();
174 for (std::size_t p = i; p <= j; ++p) {
175 cur += bits[p] ? +1 : -1;
176 if (cur < mn) {
177 mn = cur;
178 }
179 }
180 return mn;
181 }
182
183 std::size_t range_max_query_pos(std::size_t i, std::size_t j) const {
184 if (i > j || j >= num_bits) {
185 return npos;
186 }
187 int cur = 0, mx = std::numeric_limits<int>::min();
188 std::size_t pos = npos;
189 for (std::size_t p = i; p <= j; ++p) {
190 cur += bits[p] ? +1 : -1;
191 if (cur > mx) {
192 mx = cur;
193 pos = p;
194 }
195 }
196 return pos;
197 }
198
199 int range_max_query_val(std::size_t i, std::size_t j) const {
200 if (i > j || j >= num_bits) {
201 return 0;
202 }
203 int cur = 0, mx = std::numeric_limits<int>::min();
204 for (std::size_t p = i; p <= j; ++p) {
205 cur += bits[p] ? +1 : -1;
206 if (cur > mx) {
207 mx = cur;
208 }
209 }
210 return mx;
211 }
212
213 std::size_t mincount(std::size_t i, std::size_t j) const {
214 if (i > j || j >= num_bits) {
215 return 0;
216 }
217 int cur = 0, mn = std::numeric_limits<int>::max();
218 for (std::size_t p = i; p <= j; ++p) {
219 cur += bits[p] ? +1 : -1;
220 if (cur < mn) {
221 mn = cur;
222 }
223 }
224 std::size_t cnt = 0;
225 cur = 0;
226 for (std::size_t p = i; p <= j; ++p) {
227 cur += bits[p] ? +1 : -1;
228 if (cur == mn) {
229 ++cnt;
230 }
231 }
232 return cnt;
233 }
234
235 // (1-based q)
236 std::size_t minselect(std::size_t i, std::size_t j, std::size_t q) const {
237 if (i > j || j >= num_bits || q == 0) {
238 return npos;
239 }
240 int cur = 0, mn = std::numeric_limits<int>::max();
241 for (std::size_t p = i; p <= j; ++p) {
242 cur += bits[p] ? +1 : -1;
243 if (cur < mn) {
244 mn = cur;
245 }
246 }
247 cur = 0;
248 for (std::size_t p = i; p <= j; ++p) {
249 cur += bits[p] ? +1 : -1;
250 if (cur == mn) {
251 if (--q == 0) {
252 return p;
253 }
254 }
255 }
256 return npos;
257 }
258
259 std::size_t close(std::size_t i) const {
260 if (i >= num_bits) {
261 return npos;
262 }
263 return fwdsearch(i, -1);
264 }
265 std::size_t open(std::size_t i) const {
266 if (i == 0 || i > num_bits) {
267 return npos;
268 }
269 auto r = bwdsearch(i, 0);
270 return (r == npos ? npos : r + 1);
271 }
272 std::size_t enclose(std::size_t i) const {
273 if (i == 0 || i > num_bits) {
274 return npos;
275 }
276 auto r = bwdsearch(i, -2);
277 return (r == npos ? npos : r + 1);
278 }
279};