48 const size_t RangeMinimumQuery::catalan_numbers_[17][17] = {
49 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
50 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
51 { 0, 0, 2, 5, 9, 14, 20, 27, 35, 44, 54, 65, 77, 90, 104, 119, 135 },
52 { 0, 0, 0, 5, 14, 28, 48, 75, 110, 154, 208, 273, 350, 440, 544, 663, 798 },
53 { 0, 0, 0, 0, 14, 42, 90, 165, 275, 429, 637, 910, 1260, 1700, 2244, 2907, 3705 },
54 { 0, 0, 0, 0, 0, 42, 132, 297, 572, 1001, 1638, 2548, 3808, 5508, 7752, 10659, 14364 },
55 { 0, 0, 0, 0, 0, 0, 132, 429, 1001, 2002, 3640, 6188, 9996, 15504, 23256, 33915, 48279 },
56 { 0, 0, 0, 0, 0, 0, 0, 429, 1430, 3432, 7072, 13260, 23256, 38760, 62016, 95931, 144210 },
57 { 0, 0, 0, 0, 0, 0, 0, 0, 1430, 4862, 11934, 25194, 48450, 87210, 149226, 245157, 389367 },
58 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 4862, 16796, 41990, 90440, 177650, 326876, 572033, 961400 },
59 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16796, 58786, 149226, 326876, 653752, 1225785, 2187185 },
60 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58786, 208012, 534888, 1188640, 2414425, 4601610 },
61 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208012, 742900, 1931540, 4345965, 8947575 },
62 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 742900, 2674440, 7020405, 15967980 },
63 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2674440, 9694845, 25662825 },
64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9694845, 35357670 },
65 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35357670 }
72 const unsigned char RangeMinimumQuery::log_table_256_[256] =
74 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
75 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
76 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
77 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
78 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
79 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
80 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
81 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
82 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
83 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
84 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
85 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
86 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
87 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
88 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
89 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
95 const unsigned char RangeMinimumQuery::lsb_table_256_[256] =
97 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
98 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
99 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
100 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
101 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
102 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
103 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
104 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
105 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
106 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
107 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
108 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
109 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
110 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
111 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
112 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
145 : array_( std::move( array ))
166 if( i >= array_.size() || j >= array_.size() || j < i ) {
167 throw std::invalid_argument(
168 "Invalid range minimum query with indices i==" +
176 size_t naive_min = j;
177 for(
size_t x = i; x < j; x++ ) {
178 if( array_[x] < array_[naive_min] ) {
185 size_t mb_i = microblock_(i);
186 size_t mb_j = microblock_(j);
187 size_t min, min_i, min_j;
188 size_t s_mi = mb_i * micro_size_;
189 size_t i_pos = i - s_mi;
192 min_i = clearbits_(precomputed_queries_(block_types_[mb_i], j-s_mi), i_pos);
193 min = min_i == 0 ? j : s_mi + lsb_(min_i);
195 size_t b_i = block_(i);
196 size_t b_j = block_(j);
197 size_t s_mj = mb_j * micro_size_;
198 size_t j_pos = j - s_mj;
199 min_i = clearbits_(precomputed_queries_(block_types_[mb_i], micro_size_-1), i_pos);
200 min = min_i == 0 ? s_mi + micro_size_ - 1 : s_mi + lsb_(min_i);
203 if( precomputed_queries_(block_types_[mb_j], j_pos) == 0 ) {
206 min_j = s_mj + lsb_(precomputed_queries_(block_types_[mb_j], j_pos));
208 if( array_[min_j] < array_[min] ) {
212 if( mb_j > mb_i + 1 ) {
213 size_t s_bi = b_i * block_size_;
214 size_t s_bj = b_j * block_size_;
215 if( s_bi+micro_size_ > i ) {
219 if( precomputed_queries_(block_types_[mb_i], micro_size_-1) == 0 ) {
220 min_i = s_bi + block_size_ - 1;
222 min_i = s_mi + micro_size_ + lsb_(
223 precomputed_queries_(block_types_[mb_i], micro_size_-1)
226 if( array_[min_i] < array_[min] ) {
230 if( j >= s_bj+micro_size_ ) {
234 if( precomputed_queries_(block_types_[mb_j], micro_size_-1) == 0 ) {
237 min_j = s_bj + lsb_(precomputed_queries_(block_types_[mb_j], micro_size_-1));
239 if( array_[min_j] < array_[min] ) {
244 size_t block_difference = b_j - b_i;
245 if( block_difference > 1 ) {
246 size_t k, twotothek, block_tmp;
248 if( s_bj - s_bi - block_size_ <= super_size_ ) {
249 k = log2fast_(block_difference - 2);
252 j = m_(k, b_j-twotothek);
253 min_i = array_[i] <= array_[j] ? i : j;
256 size_t sb_i = superblock_(i);
257 size_t sb_j = superblock_(j);
259 block_tmp = block_((sb_i+1)*super_size_);
260 k = log2fast_(block_tmp - b_i);
263 j = m_(k, block_tmp+1-twotothek);
264 min_i = array_[i] <= array_[j] ? i : j;
266 block_tmp = block_(sb_j*super_size_);
267 k = log2fast_(b_j - block_tmp);
270 i = m_(k, block_tmp);
271 j = m_(k, b_j-twotothek);
272 min_j = array_[i] <= array_[j] ? i : j;
274 if( array_[min_j] < array_[min_i] ) {
278 if( sb_j > sb_i + 1 ) {
279 k = log2fast_(sb_j - sb_i - 2);
281 i = m_prime_(k, sb_i+1);
282 j = m_prime_(k, sb_j-twotothek);
283 min_j = array_[i] <= array_[j] ? i : j;
284 if (array_[min_j] < array_[min_i]) {
290 if( array_[min_i] < array_[min] ) {
307 void RangeMinimumQuery::init_()
309 micro_size_ = 1 << 3;
310 block_size_ = 1 << 4;
311 super_size_ = 1 << 8;
313 auto const n = array_.size();
318 auto const micro_count = microblock_(n-1)+1;
319 auto const block_count = block_(n-1)+1;
320 auto const super_count = superblock_(n-1)+1;
330 if( block_count < super_size_ / (2*block_size_) ) {
336 block_types_ = std::vector<BlockTypeType>(micro_count);
338 precomputed_queries_ = Matrix<SuccinctType>(
339 catalan_numbers_[micro_size_][micro_size_], micro_size_
341 for(
size_t i = 0; i < catalan_numbers_[micro_size_][micro_size_]; i++ ) {
342 precomputed_queries_(i, 0) = 1;
345 std::vector<IntType> rp(micro_size_+1);
351 rp[0] = std::numeric_limits<IntType>::min();
354 std::vector<size_t> gstack( micro_size_ );
358 for(
size_t i = 0; i < micro_count; i++ ) {
360 end = start + micro_size_;
373 while( rp[q-p-1] > array_[z] ) {
374 block_types_[i] += catalan_numbers_[p][q];
382 if( precomputed_queries_(block_types_[i], 0) == 1 ) {
383 precomputed_queries_(block_types_[i], 0) = 0;
385 for(
size_t j = start; j < end; j++ ) {
386 while( gstacksize > 0 && (array_[j] < array_[gstack[gstacksize-1]]) ) {
389 if( gstacksize > 0 ) {
390 g = gstack[gstacksize-1];
391 precomputed_queries_(block_types_[i], j-start)
392 = precomputed_queries_(block_types_[i], g-start) | (1 << (g % micro_size_));
394 precomputed_queries_(block_types_[i], j-start) = 0;
396 gstack[gstacksize++] = j;
402 auto M_depth =
static_cast<size_t>(
403 floor( log2(
static_cast<double>( super_size_ ) /
static_cast<double>( block_size_ ) ))
405 m_matrix_ = Matrix<SuccinctType>(M_depth, block_count);
407 auto Mprime_depth =
static_cast<size_t>( floor(log2(super_count)) ) + 1;
408 m_prime_ = Matrix<size_t>(Mprime_depth, super_count);
414 for(
size_t i = 0; i < block_count; i++ ) {
417 end = start + block_size_;
421 if( array_[z] < array_[q] ) {
426 if( array_[z] < array_[p] ) {
429 if( array_[z] < array_[q] ) {
433 m_matrix_(0, i) = p-start;
434 if( z % super_size_ == 0 || z == n ) {
435 m_prime_(0, g++) = q;
442 for(
size_t j = 1; j < M_depth; j++ ) {
443 for(
size_t i = 0; i < block_count - dist; i++ ) {
445 if( array_[m_(j-1, i)] <= array_[m_(j-1,i+dist)] ) {
446 m_matrix_(j, i) = m_matrix_(j-1, i);
448 m_matrix_(j, i) = m_matrix_(j-1, i+dist) + (dist*block_size_);
451 for (
size_t i = block_count - dist; i < block_count; i++) {
452 m_matrix_(j, i) = m_matrix_(j-1, i);
459 for(
size_t j = 1; j < Mprime_depth; j++ ) {
460 for(
size_t i = 0; i < super_count - dist; i++ ) {
462 if( array_[m_prime_(j-1, i)] <= array_[m_prime_(j-1, i+dist)] ) {
463 m_prime_(j, i) = m_prime_(j-1, i);
465 m_prime_(j, i) = m_prime_(j-1, i+dist);
468 for (
size_t i = super_count - dist; i < super_count; i++) {
469 m_prime_(j, i) = m_prime_(j-1, i);
478 size_t RangeMinimumQuery::log2fast_(
size_t v )
const
483 if(( tt = v >> 16 )) {
484 c = (t = v >> 24) ? 24 + log_table_256_[t] : 16 + log_table_256_[tt & 0xFF];
486 c = (t = v >> 8) ? 8 + log_table_256_[t] : log_table_256_[v];
496 return n & highest_bits_set_[x];