9#include "cplib/port/bit.hpp"
10#include "cplib/range/sparse_table.hpp"
18 using bitmap_t = uint64_t;
19 static constexpr int bitmap_size = std::numeric_limits<bitmap_t>::digits;
21 template <
typename InputIt,
typename Comp>
22 RangeMinBlock(InputIt first, InputIt last, Comp comp) {
23 using T =
typename std::iterator_traits<InputIt>::value_type;
25 static std::vector<std::pair<T, int>> monotonic_stack;
26 monotonic_stack.clear();
28 for (
auto it = first; it != last; it++) {
29 while (!monotonic_stack.empty() && comp(*it, monotonic_stack.back().first)) {
30 monotonic_stack.pop_back();
32 if (monotonic_stack.empty()) {
35 int prev_idx = monotonic_stack.back().second;
36 min_loc[idx] = min_loc[prev_idx] | (bitmap_t(1) << prev_idx);
38 monotonic_stack.emplace_back(*it, idx);
43 int min_idx_inclusive(
int left,
int right)
const {
44 bitmap_t loc = min_loc[right] & ~((bitmap_t(1) << left) - 1);
45 return loc == 0 ? right : port::countr_zero(loc);
50 std::array<bitmap_t, bitmap_size> min_loc;
53template <
typename T,
typename Comp>
56 const T& operator()(
const T& a,
const T& b)
const {
return std::min(a, b, comp); }
73template <
typename T,
typename Comp = std::less<T>>
76 static constexpr int block_size = impl::RangeMinBlock::bitmap_size;
77 using size_type = std::size_t;
86 RangeMinQuery(std::vector<T>&& arr) : data(std::move(arr)) { _build(); }
94 template <
typename InputIt>
100 size_type
size()
const {
return data.size(); }
110 T
range_min(size_type left, size_type right)
const {
return _range_min_inclusive(left, right - 1); }
114 std::vector<impl::RangeMinBlock> blocks;
119 size_type num_blocks = (data.size() + block_size - 1) / block_size;
121 blocks.reserve(num_blocks);
122 for (size_type i = 0; i + 1 < num_blocks; i++) {
123 auto begin = data.begin() + i * block_size;
124 blocks.emplace_back(begin, begin + block_size, comp);
126 blocks.emplace_back(data.begin() + (num_blocks - 1) * block_size, data.end(), comp);
127 std::vector<T> block_min;
128 block_min.reserve(num_blocks);
129 for (size_type i = 0; i + 1 < num_blocks; i++) {
130 block_min.push_back(data[i * block_size + blocks[i].min_idx_inclusive(0, block_size - 1)]);
132 block_min.push_back(data[(num_blocks - 1) * block_size +
133 blocks.back().min_idx_inclusive(0, (data.size() + block_size - 1) % block_size)]);
134 block_table = SparseTable<T, impl::MinOp<T, Comp>>(std::move(block_min));
137 T _range_min_inclusive(size_type left, size_type right)
const {
138 size_type left_block = left / block_size, right_block = right / block_size;
139 if (left_block == right_block) {
140 int block_idx = blocks[left_block].min_idx_inclusive(left % block_size, right % block_size);
141 return data[left_block * block_size + block_idx];
143 int left_block_idx = blocks[left_block].min_idx_inclusive(left % block_size, block_size - 1);
144 int right_block_idx = blocks[right_block].min_idx_inclusive(0, right % block_size);
145 const T& left_block_min = data[left_block * block_size + left_block_idx];
146 const T& right_block_min = data[right_block * block_size + right_block_idx];
147 const T& lr_block_min = std::min(left_block_min, right_block_min, comp);
148 if (left_block + 1 == right_block) {
151 return std::min(lr_block_min, block_table.
range(left_block + 1, right_block), comp);
Efficient static range minimum query.
Definition: rmq.hpp:74
RangeMinQuery()=default
Creates an empty RangeMinQuery.
RangeMinQuery(std::vector< T > &&arr)
Construct the range minumum query object from the given sequence.
Definition: rmq.hpp:86
T range_min(size_type left, size_type right) const
Returns the minimum element in the 0-based half-open range [left, right).
Definition: rmq.hpp:110
RangeMinQuery(InputIt first, InputIt last)
Construct the range minumum query object from the given sequence.
Definition: rmq.hpp:95
size_type size() const
Returns number of elements in the sequence.
Definition: rmq.hpp:100
RangeMinQuery(const std::vector< T > &arr)
Construct the range minumum query object from the given sequence.
Definition: rmq.hpp:83
sparse table for certain binary operations like min and gcd.
Definition: sparse_table.hpp:19
T range(size_type left, size_type right) const
Iterated application of operator Op on elements in the 0-based half-open range [left,...
Definition: sparse_table.hpp:60