Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
wavelet_matrix.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2
3using ull=unsigned long long;
5 static const ull NOTFOUND=0xFFFFFFFFFFFFFFFFLLU;
6
7private:
8 const ull size;
9 static const ull blockBitNum=16;
10 static const ull LEVEL_L=512;
11 static const ull LEVEL_S=16;
12 vector<ull>L;
13 vector<unsigned short>S;
14 vector<unsigned short>B;
15 ull numOne=0;
16
17public:
18 explicit SuccinctBitVector(const ull n):size(n) {
19 const ull s=(n+blockBitNum-1)/blockBitNum+1;
20 this->B.assign(s,0);
21 this->L.assign(n/LEVEL_L+1,0);
22 this->S.assign(n/LEVEL_S+1,0);
23 }
24 void set_bit(const ull bit,const ull pos) {
25 assert(bit==0 or bit==1);
26 assert(pos<this->size);
27 const ull blockPos=pos/blockBitNum;
28 const ull offset=pos%blockBitNum;
29 if(bit==1) {
30 B.at(blockPos)|=(1LLU<<offset);
31 }else{
32 B.at(blockPos)&=(~(1LLU<<offset));
33 }
34 }
35 ull access(const ull pos) {
36 assert(pos<this->size);
37 const ull blockPos=pos/blockBitNum;
38 const ull offset=pos%blockBitNum;
39 return((B.at(blockPos)>>offset)&1);
40 }
41 void build() {
42 ull num=0;
43 for(ull i=0;i<=size;i++) {
44 if(i%LEVEL_L==0)L.at(i/LEVEL_L)=num;
45 if(i%LEVEL_S==0)S.at(i/LEVEL_S)=num-L.at(i/LEVEL_L);
46 if(i!=size and i%blockBitNum==0)num+=this->pop_count(this->B.at(i/blockBitNum));
47 }
48 this->numOne=num;
49 }
50 ull rank(const ull bit,const ull pos) {
51 assert(bit==0 or bit==1);
52 assert(pos<=this->size);
53 if(bit) {
54 return L[pos/LEVEL_L]+S[pos/LEVEL_S]+pop_count(B[pos/blockBitNum]&((1<<(pos%blockBitNum))-1));
55 }else{
56 return pos-rank(1,pos);
57 }
58 }
59 ull select(const ull bit,const ull rank) {
60 assert(bit==0 or bit==1);
61 assert(rank>0);
62 if(bit==0 and rank>this->size-this->numOne)return NOTFOUND;
63 if(bit==1 and rank>this->numOne)return NOTFOUND;
64 ull large_idx=0;
65 {
66 ull left=0;
67 ull right=L.size();
68 while(right-left>1) {
69 ull mid=(left+right)/2;
70 ull r=L.at(mid);
71 r=(bit)?r:mid*LEVEL_L-L.at(mid);
72 if(r<rank) {
73 left=mid;
74 large_idx=mid;
75 }else{
76 right=mid;
77 }
78 }
79 }
80 ull small_idx=(large_idx*LEVEL_L)/LEVEL_S;
81 {
82 ull left=(large_idx*LEVEL_L)/LEVEL_S;
83 ull right=min(((large_idx+1)*LEVEL_L)/LEVEL_S,(ull)S.size());
84 while(right-left>1) {
85 ull mid=(left+right)/2;
86 ull r=L.at(large_idx)+S.at(mid);
87 r=(bit)?r:mid*LEVEL_S-r;
88 if(r<rank) {
89 left=mid;
90 small_idx=mid;
91 }else{
92 right=mid;
93 }
94 }
95 }
96 ull rank_pos=0;
97 {
98 const ull begin_block_idx=(small_idx*LEVEL_S)/blockBitNum;
99 ull total_bit=L.at(large_idx)+S.at(small_idx);
100 if(bit==0) {
101 total_bit=small_idx*LEVEL_S-total_bit;
102 }
103 for(ull i=0;;++i) {
104 ull b=pop_count(B.at(begin_block_idx+i));
105 if(bit==0)b=blockBitNum-b;
106 if(total_bit+b>=rank) {
107 ull block=(bit)?B.at(begin_block_idx+i):~B.at(begin_block_idx+i);
108 rank_pos=(begin_block_idx+i)*blockBitNum+select_in_block(block,rank-total_bit);
109 break;
110 }
111 total_bit+=b;
112 }
113 }
114 return rank_pos+1;
115 }
116 ull get_num_one()const{
117 return numOne;
118 }
119
120private:
121 ull pop_count(ull x) {
122 x=(x&0x5555555555555555ULL)+((x>>1)&0x5555555555555555ULL);
123 x=(x&0x3333333333333333ULL)+((x>>2)&0x3333333333333333ULL);
124 x=(x+(x>>4))&0x0f0f0f0f0f0f0f0fULL;
125 x=x+(x>>8);
126 x=x+(x>>16);
127 x=x+(x>>32);
128 return x&0x7FLLU;
129 }
130 ull select_in_block(ull x,ull rank) {
131 ull x1=x-((x&0xAAAAAAAAAAAAAAAALLU)>>1);
132 ull x2=(x1&0x3333333333333333LLU)+((x1>>2)&0x3333333333333333LLU);
133 ull x3=(x2+(x2>>4))&0x0F0F0F0F0F0F0F0FLLU;
134 ull pos=0;
135 for(;;pos+=8) {
136 ull rank_next=(x3>>pos)&0xFFLLU;
137 if(rank<=rank_next)break;
138 rank-=rank_next;
139 }
140 ull v2=(x2>>pos)&0xFLLU;
141 if(rank>v2) {
142 rank-=v2;
143 pos+=4;
144 }
145 ull v1=(x1>>pos)&0x3LLU;
146 if(rank>v1) {
147 rank-=v1;
148 pos+=2;
149 }
150 ull v0=(x>>pos)&0x1LLU;
151 if(v0<rank) {
152 rank-=v0;
153 pos+=1;
154 }
155 return pos;
156 }
157};
158
159/// @brief Wavelet Matrix
160/// @ref https://github.com/MitI-7/WaveletMatrix/tree/master/WaveletMatrix
161/// @ref https://miti-7.hatenablog.com/entry/2019/02/01/152131
164
165private:
166 vector<SuccinctBitVector>bit_arrays;
167 vector<ull>begin_one;
168 map<ull,ull>begin_alphabet;
169 vector<vector<ull>>cumulative_sum;
170 ull size;
171 ull maximum_element;
172 ull bit_size;
173
174public:
175 /// @brief コンストラクタ
176 /// @brief a から Wavelet Matrix を構築する
177 WaveletMatrix(const vector<ull>&a) {
178 assert(a.size()>0);
179 size=a.size();
180 maximum_element=*max_element(a.begin(),a.end())+1;
181 bit_size=get_num_of_bit(maximum_element);
182 if(bit_size==0)bit_size=1;
183 for(ull i=0;i<bit_size;++i) {
184 SuccinctBitVector sv(size);
185 bit_arrays.push_back(sv);
186 }
187 this->begin_one.resize(bit_size);
188 this->cumulative_sum.resize(bit_size+1,vector<ull>(size+1,0));
189 for(ull j=0;j<a.size();++j) {
190 this->cumulative_sum.at(0).at(j+1)=this->cumulative_sum.at(0).at(j)+a[j];
191 }
192 vector<ull>v(a);
193 for(ull i=0;i<bit_size;++i) {
194 vector<ull>temp;
195 for(ull j=0;j<v.size();++j) {
196 ull c=v.at(j);
197 ull bit=(c>>(bit_size-i-1))&1;
198 if(bit==0) {
199 temp.push_back(c);
200 bit_arrays.at(i).set_bit(0,j);
201 }
202 }
203 this->begin_one.at(i)=temp.size();
204 for(ull j=0;j<v.size();++j) {
205 ull c=v.at(j);
206 ull bit=(c>>(bit_size-i-1))&1;
207 if(bit==1) {
208 temp.push_back(c);
209 bit_arrays.at(i).set_bit(1,j);
210 }
211 }
212 for(ull j=0;j<temp.size();++j) {
213 this->cumulative_sum.at(i+1).at(j+1)=this->cumulative_sum.at(i+1).at(j)+temp.at(j);
214 }
215 bit_arrays.at(i).build();
216 v=temp;
217 }
218 for(int i=v.size()-1;i>=0;--i)this->begin_alphabet[v.at(i)]=i;
219 }
220
221 /// @brief a[pos] を返す
222 /// @note O(log σ)
223 ull access(ull pos) {
224 if(pos>=this->size)return NOTFOUND;
225 ull c=0;
226 for(ull i=0;i<bit_arrays.size();++i) {
227 ull bit=bit_arrays.at(i).access(pos);
228 c=(c<<1)|bit;
229 pos=bit_arrays.at(i).rank(bit,pos);
230 if(bit)pos+=this->begin_one.at(i);
231 }
232 return c;
233 }
234
235 /// @brief rank 番目の c の位置 +1 を返す
236 /// @brief rank は 1-indexed
237 /// @note O(log σ)
238 ull select(ull c,ull rank) {
239 assert(rank>0);
240 if(c>=maximum_element)return NOTFOUND;
241 if(this->begin_alphabet.find(c)==this->begin_alphabet.end())return NOTFOUND;
242 ull index=this->begin_alphabet.at(c)+rank;
243 for(ull i=0;i<bit_arrays.size();++i) {
244 ull bit=((c>>i)&1);
245 if(bit==1)index-=this->begin_one.at(bit_size-i-1);
246 index=this->bit_arrays.at(bit_size-i-1).select(bit,index);
247 }
248 return index;
249 }
250
251 /// @brief 区間 [l, r) で最大のインデックスを返す
252 /// @note O(log σ)
253 ull max_range(ull begin_pos,ull end_pos) {
254 return quantile_range(begin_pos,end_pos,end_pos-begin_pos-1);
255 }
256
257 /// @brief 区間 [l, r) で最小のインデックスを返す
258 /// @note O(log σ)
259 ull min_range(ull begin_pos,ull end_pos) {
260 return quantile_range(begin_pos,end_pos,0);
261 }
262
263 /// @brief 区間 [l, r) で k 番目に小さい値のインデックスを返す
264 /// @brief k は 0-indexed
265 /// @note O(log σ)
266 ull quantile_range(ull begin_pos,ull end_pos,ull k) {
267 if((end_pos>size||begin_pos>=end_pos)||(k>=end_pos-begin_pos))return NOTFOUND;
268 ull val=0;
269 for(ull i=0;i<bit_size;++i) {
270 const ull num_of_zero_begin=bit_arrays.at(i).rank(0,begin_pos);
271 const ull num_of_zero_end=bit_arrays.at(i).rank(0,end_pos);
272 const ull num_of_zero=num_of_zero_end-num_of_zero_begin;
273 const ull bit=(k<num_of_zero)?0:1;
274 if(bit) {
275 k-=num_of_zero;
276 begin_pos=this->begin_one.at(i)+begin_pos-num_of_zero_begin;
277 end_pos=this->begin_one.at(i)+end_pos-num_of_zero_end;
278 }else{
279 begin_pos=num_of_zero_begin;
280 end_pos=num_of_zero_begin+num_of_zero;
281 }
282 val=((val<<1)|bit);
283 }
284 ull left=0;
285 for(ull i=0;i<bit_size;++i) {
286 const ull bit=(val>>(bit_size-i-1))&1;
287 left=bit_arrays.at(i).rank(bit,left);
288 if(bit)left+=this->begin_one.at(i);
289 }
290 const ull rank=begin_pos+k-left+1;
291 return select(val,rank)-1;
292 }
293
294 /// @brief 区間 [0, pos) の c の数
295 /// @note O(log σ)
296 ull rank(ull c,ull pos) {
297 assert(pos<size);
298 if(c>=maximum_element)return 0;
299 if(this->begin_alphabet.find(c)==this->begin_alphabet.end())return 0;
300 for(ull i=0;i<bit_size;++i) {
301 ull bit=(c>>(bit_size-i-1))&1;
302 pos=bit_arrays.at(i).rank(bit,pos);
303 if(bit)pos+=this->begin_one.at(i);
304 }
305 ull begin_pos=this->begin_alphabet.at(c);
306 return pos-begin_pos;
307 }
308
309 /// @brief 区間 [l, r) の [min_c, max_c) に入る値の個数
310 /// @note O(log σ)
311 ull range_freq(ull begin_pos,ull end_pos,ull min_c,ull max_c) {
312 if((end_pos>size||begin_pos>=end_pos)||(min_c>=max_c)||min_c>=maximum_element) {
313 return 0;
314 }
315 const auto maxi_t=rank_all(max_c,begin_pos,end_pos);
316 const auto mini_t=rank_all(min_c,begin_pos,end_pos);
317 return get<1>(maxi_t)-get<1>(mini_t);
318 }
319
320 /// @brief 区間 [l, r) の c より小さい値の数
321 /// @note O(log σ)
322 ull rank_less_than(ull c,ull begin,ull end) {
323 auto t=rank_all(c,begin,end);
324 return get<1>(t);
325 }
326
327 /// @brief 区間 [l, r) の c より大きい値の数
328 /// @note O(log σ)
329 ull rank_more_than(ull c,ull begin,ull end) {
330 auto t=rank_all(c,begin,end);
331 return get<2>(t);
332 }
333
334 /// @brief 区間 [l, r) の (c と同じ値の数, c より小さい値の数, c より大きい値の数)
335 /// @note O(log σ)
336 tuple<ull,ull,ull>rank_all(const ull c,ull begin,ull end) {
337 assert(end<=size);
338 const ull num=end-begin;
339 if(begin>=end)return make_tuple(0,0,0);
340 if(c>=maximum_element||end==0)return make_tuple(0,num,0);
341 ull rank_less_than=0,rank_more_than=0;
342 for(size_t i=0;i<bit_size&&begin<end;++i) {
343 const ull bit=(c>>(bit_size-i-1))&1;
344 const ull rank0_begin=this->bit_arrays.at(i).rank(0,begin);
345 const ull rank0_end=this->bit_arrays.at(i).rank(0,end);
346 const ull rank1_begin=begin-rank0_begin;
347 const ull rank1_end=end-rank0_end;
348 if(bit) {
349 rank_less_than+=(rank0_end-rank0_begin);
350 begin=this->begin_one.at(i)+rank1_begin;
351 end=this->begin_one.at(i)+rank1_end;
352 }else{
353 rank_more_than+=(rank1_end-rank1_begin);
354 begin=rank0_begin;
355 end=rank0_end;
356 }
357 }
358 const ull rank=num-rank_less_than-rank_more_than;
359 return make_tuple(rank,rank_less_than,rank_more_than);
360 }
361
362 /// @brief 区間 [l, r) で出現回数が多い順に k 個の (値, 頻度) を返す
363 /// @note O(log σ)
364 vector<pair<ull,ull>>topk(ull begin,ull end,ull k) {
365 ull s=begin,e=end;
366 assert(s<e);
367 vector<pair<ull,ull>>result;
368 auto c=[](const tuple<ull,ull,ull,ull,ull>&l,const tuple<ull,ull,ull,ull,ull>&r) {
369 if(get<0>(l)!=get<0>(r))return get<0>(l)<get<0>(r);
370 if(get<3>(l)!=get<3>(r))return get<3>(l)>get<3>(r);
371 if(get<4>(l)!=get<4>(r))return get<4>(l)>get<4>(r);
372 return true;
373 };
374 std::priority_queue<tuple<ull,ull,ull,ull,ull>,vector<tuple<ull,ull,ull,ull,ull>>,decltype(c)>que(c);//width,left,right,depth,value
375 que.push(make_tuple(e-s,s,e,0,0));
376 while(not que.empty()) {
377 auto element=que.top();
378 que.pop();
379 ull width,left,right,depth,value;
380 tie(width,left,right,depth,value)=element;
381 if(depth>=this->bit_size) {
382 result.emplace_back(make_pair(value,right-left));
383 if(result.size()>=k)break;
384 continue;
385 }
386 const ull left0=this->bit_arrays.at(depth).rank(0,left);
387 const ull right0=this->bit_arrays.at(depth).rank(0,right);
388 if(left0<right0)que.push(make_tuple(right0-left0,left0,right0,depth+1,value));
389 const ull left1=this->begin_one.at(depth)+this->bit_arrays.at(depth).rank(1,left);
390 const ull right1=this->begin_one.at(depth)+this->bit_arrays.at(depth).rank(1,right);
391 if(left1<right1)que.push(make_tuple(right1-left1,left1,right1,depth+1,value|(1<<(bit_size-depth-1))));
392 }
393 return result;
394 };
395
396 /// @brief 区間 [l, r) で [x, y) に入る値の総和
397 /// @note O(log σ)
398 ull range_sum(const ull begin,const ull end,const ull x,const ull y) {
399 return range_sum(begin,end,0,0,x,y);
400 }
401
402 ull prev_value(const ull begin_pos,const ull end_pos,const ull x,ull y) {
403 assert(end_pos<=size);
404 if(x>=y or y==0)return NOTFOUND;
405 if(y>maximum_element)y=maximum_element;
406 if(begin_pos>=end_pos)return NOTFOUND;
407 if(x>=maximum_element||end_pos==0)return NOTFOUND;
408 y--;
409 stack<tuple<ull,ull,ull,ull,bool>>s;
410 s.emplace(make_tuple(begin_pos,end_pos,0,0,true));
411 while(not s.empty()) {
412 ull b,e,depth,c;
413 bool tight;
414 tie(b,e,depth,c,tight)=s.top();
415 s.pop();
416 if(depth==bit_size) {
417 if(c>=x)return c;
418 continue;
419 }
420 const ull bit=(y>>(bit_size-depth-1))&1;
421 const ull rank0_begin=this->bit_arrays.at(depth).rank(0,b);
422 const ull rank0_end=this->bit_arrays.at(depth).rank(0,e);
423 const ull rank1_begin=b-rank0_begin;
424 const ull rank1_end=e-rank0_end;
425 const ull b0=rank0_begin;
426 const ull e0=rank0_end;
427 if(b0!=e0) {
428 const ull c0=((c<<1)|0);
429 s.emplace(make_tuple(b0,e0,depth+1,c0,tight and bit==0));
430 }
431 const ull b1=this->begin_one.at(depth)+rank1_begin;
432 const ull e1=this->begin_one.at(depth)+rank1_end;
433 if(b1!=e1) {
434 if(not tight or bit==1) {
435 const auto c1=((c<<1)|1);
436 s.emplace(make_tuple(b1,e1,depth+1,c1,tight));
437 }
438 }
439 }
440 return NOTFOUND;
441 }
442 ull next_value(const ull begin_pos,const ull end_pos,const ull x,const ull y) {
443 assert(end_pos<=size);
444 if(x>=y or y==0)return NOTFOUND;
445 if(begin_pos>=end_pos)return NOTFOUND;
446 if(x>=maximum_element||end_pos==0)return NOTFOUND;
447 stack<tuple<ull,ull,ull,ull,bool>>s;
448 s.emplace(make_tuple(begin_pos,end_pos,0,0,true));
449 while(not s.empty()) {
450 ull b,e,depth,c;
451 bool tight;
452 tie(b,e,depth,c,tight)=s.top();
453 s.pop();
454 if(depth==bit_size) {
455 if(c<y)return c;
456 continue;
457 }
458 const ull bit=(x>>(bit_size-depth-1))&1;
459 const ull rank0_begin=this->bit_arrays.at(depth).rank(0,b);
460 const ull rank0_end=this->bit_arrays.at(depth).rank(0,e);
461 const ull rank1_begin=b-rank0_begin;
462 const ull rank1_end=e-rank0_end;
463 const ull b1=this->begin_one.at(depth)+rank1_begin;
464 const ull e1=this->begin_one.at(depth)+rank1_end;
465 if(b1!=e1) {
466 const auto c1=((c<<1)|1);
467 s.emplace(make_tuple(b1,e1,depth+1,c1,tight and bit==1));
468 }
469 const ull b0=rank0_begin;
470 const ull e0=rank0_end;
471 if(b0!=e0) {
472 if(not tight or bit==0) {
473 const ull c0=((c<<1)|0);
474 s.emplace(make_tuple(b0,e0,depth+1,c0,tight));
475 }
476 }
477 }
478 return NOTFOUND;
479 }
480 vector<tuple<ull,ull,ull>>intersect(ull _s1,ull _e1,ull _s2,ull _e2) {
481 assert(_s1<_e1);
482 assert(_s2<_e2);
483 vector<tuple<ull,ull,ull>>intersection;
484 queue<tuple<ull,ull,ull,ull,ull,ull>>que;
485 que.push(make_tuple(_s1,_e1,_s2,_e2,0,0));
486 while(not que.empty()) {
487 auto e=que.front();
488 que.pop();
489 ull s1,e1,s2,e2,depth,value;
490 tie(s1,e1,s2,e2,depth,value)=e;
491 if(depth>=this->bit_size) {
492 intersection.emplace_back(make_tuple(value,e1-s1,e2-s2));
493 continue;
494 }
495 ull s1_0=this->bit_arrays.at(depth).rank(0,s1);
496 ull e1_0=this->bit_arrays.at(depth).rank(0,e1);
497 ull s2_0=this->bit_arrays.at(depth).rank(0,s2);
498 ull e2_0=this->bit_arrays.at(depth).rank(0,e2);
499 if(s1_0!=e1_0 and s2_0!=e2_0)que.push(make_tuple(s1_0,e1_0,s2_0,e2_0,depth+1,value));
500 ull s1_1=this->begin_one.at(depth)+this->bit_arrays.at(depth).rank(1,s1);
501 ull e1_1=this->begin_one.at(depth)+this->bit_arrays.at(depth).rank(1,e1);
502 ull s2_1=this->begin_one.at(depth)+this->bit_arrays.at(depth).rank(1,s2);
503 ull e2_1=this->begin_one.at(depth)+this->bit_arrays.at(depth).rank(1,e2);
504 if(s1_1!=e1_1 and s2_1!=e2_1)que.push(make_tuple(s1_1,e1_1,s2_1,e2_1,depth+1,value|(1<<(bit_size-depth-1))));
505 }
506 return intersection;
507 };
508
509private:
510 ull get_num_of_bit(ull x) {
511 if(x==0)return 0;
512 x--;
513 ull bit_num=0;
514 while(x>>bit_num)++bit_num;
515 return bit_num;
516 }
517 ull range_sum(const ull begin, const ull end, const ull depth, const ull c, const ull x, const ull y) {
518 if(begin==end)return 0;
519 if(depth==bit_size) {
520 if(x<=c and c<y) return c*(end-begin);
521 return 0;
522 }
523 const ull next_c=((ull)1<<(bit_size-depth-1))|c;
524 const ull all_one_c=(((ull)1<<(bit_size-depth-1))-1)|next_c;
525 if(all_one_c<x or y<=c)return 0;
526 if(x<=c and all_one_c<y) return this->cumulative_sum.at(depth).at(end)-this->cumulative_sum.at(depth).at(begin);
527 const ull rank0_begin=this->bit_arrays.at(depth).rank(0,begin);
528 const ull rank0_end=this->bit_arrays.at(depth).rank(0,end);
529 const ull rank1_begin=begin-rank0_begin;
530 const ull rank1_end=end-rank0_end;
531 return range_sum(rank0_begin,rank0_end,depth+1,c,x,y)+range_sum(this->begin_one.at(depth)+rank1_begin,this->begin_one[depth]+rank1_end,depth+1,next_c,x,y);
532 }
533};
void set_bit(const ull bit, const ull pos)
ull rank(const ull bit, const ull pos)
SuccinctBitVector(const ull n)
static const ull NOTFOUND
ull access(const ull pos)
ull select(const ull bit, const ull rank)
Wavelet Matrix https://github.com/MitI-7/WaveletMatrix/tree/master/WaveletMatrix https://miti-7....
vector< tuple< ull, ull, ull > > intersect(ull _s1, ull _e1, ull _s2, ull _e2)
ull rank_more_than(ull c, ull begin, ull end)
区間 [l, r) の c より大きい値の数
ull range_freq(ull begin_pos, ull end_pos, ull min_c, ull max_c)
区間 [l, r) の [min_c, max_c) に入る値の個数
ull range_sum(const ull begin, const ull end, const ull x, const ull y)
区間 [l, r) で [x, y) に入る値の総和
ull select(ull c, ull rank)
rank 番目の c の位置 +1 を返す
ull quantile_range(ull begin_pos, ull end_pos, ull k)
区間 [l, r) で k 番目に小さい値のインデックスを返す
WaveletMatrix(const vector< ull > &a)
コンストラクタ
vector< pair< ull, ull > > topk(ull begin, ull end, ull k)
区間 [l, r) で出現回数が多い順に k 個の (値, 頻度) を返す
ull access(ull pos)
a[pos] を返す
ull next_value(const ull begin_pos, const ull end_pos, const ull x, const ull y)
ull max_range(ull begin_pos, ull end_pos)
区間 [l, r) で最大のインデックスを返す
ull min_range(ull begin_pos, ull end_pos)
区間 [l, r) で最小のインデックスを返す
tuple< ull, ull, ull > rank_all(const ull c, ull begin, ull end)
区間 [l, r) の (c と同じ値の数, c より小さい値の数, c より大きい値の数)
ull rank(ull c, ull pos)
区間 [0, pos) の c の数
ull rank_less_than(ull c, ull begin, ull end)
区間 [l, r) の c より小さい値の数
ull prev_value(const ull begin_pos, const ull end_pos, const ull x, ull y)
static const ull NOTFOUND