31 static constexpr std::size_t npos =
33 static constexpr Index invalid_index = std::numeric_limits<Index>::max();
50 explicit SegmentTree(std::span<const T> values, Compare compare = Compare())
51 : values_(values), compare_(compare) {
60 std::size_t
size_impl()
const {
return values_.size(); }
68 T
value_at_impl(std::size_t position)
const {
return values_[position]; }
80 std::size_t
arg_min_impl(std::size_t left, std::size_t right)
const {
81 if (left >= right || right > values_.size()) {
87 std::size_t answer = npos;
88 while (left < right) {
89 if ((left & 1u) != 0) {
90 answer = better(answer, tree_[left]);
93 if ((right & 1u) != 0) {
95 answer = better(answer, tree_[right]);
110 return sizeof(*this) + pixie::vector_capacity_bytes(tree_);
125 std::size_t better(std::size_t left, std::size_t right)
const {
126 if (left == npos || left == invalid_index) {
129 if (right == npos || right == invalid_index) {
132 if (compare_(values_[right], values_[left])) {
135 if (compare_(values_[left], values_[right])) {
138 return std::min(left, right);
151 Index build_better(Index left, Index right)
const {
152 if (left == invalid_index) {
155 if (right == invalid_index) {
158 return compare_(values_[right], values_[left]) ? right : left;
173 if (values_.empty()) {
176 if (values_.size() >
static_cast<std::size_t
>(invalid_index)) {
177 throw std::length_error(
"RMQ segment tree index type is too small");
180 leaf_base_ = std::bit_ceil(values_.size());
182 tree_.resize(2 * leaf_base_);
183 for (std::size_t i = 0; i < values_.size(); ++i) {
184 tree_[leaf_base_ + i] =
static_cast<Index
>(i);
186 std::fill(tree_.begin() + leaf_base_ + values_.size(), tree_.end(),
188 for (std::size_t node = leaf_base_; node > 1;) {
190 tree_[node] = build_better(tree_[node << 1], tree_[(node << 1) | 1]);
194 std::span<const T> values_;
196 std::size_t leaf_base_ = 0;
197 std::vector<Index> tree_;
SegmentTree(std::span< const T > values, Compare compare=Compare())
Build an iterative segment tree over values.
Definition segment_tree.h:50
std::size_t arg_min_impl(std::size_t left, std::size_t right) const
Return the first minimum position in [left, right).
Definition segment_tree.h:80