m1une's library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: Range Update Range Max
(acted_monoid/range_update_range_max.hpp)

Overview

An Acted Monoid representing Range Update (overwrite) operations and Range Maximum queries.

Important Usage Note

Similar to RangeUpdateRangeMin, this implementation uses std::optional<T> as the operator_type to safely represent the state of “no operation” (the identity element of the operator monoid).

Example

#include "ds/segtree/lazy_segtree.hpp"
#include "acted_monoid/range_update_range_max.hpp"
#include <iostream>
#include <vector>

using AM = m1une::acted_monoid::RangeUpdateRangeMax<long long>;

int main() {
    std::vector<long long> A = {10, 20, 30, 40, 50};
    m1une::ds::LazySegtree<AM> seg(A);

    // Overwrite range [1, 4) with 100 -> {10, 100, 100, 100, 50}
    seg.apply(1, 4, std::optional<long long>(100));

    // Get max of [0, 2) -> max(10, 100) = 100
    std::cout << seg.prod(0, 2) << "\n";

    return 0;
}

Interface and Complexity

This is a stateless acted-monoid tag. Lazy data structures use its public value_type, operator_type, id(), op(a, b), op_id(), op_comp(f, g), and mapping(f, x) members. Helpers such as make(...), shifted mappings, or reversal-aware mappings are described above when the header provides them.

The static operations are $O(1)$ for the scalar metadata stored by these range acted monoids, aside from the cost of the underlying arithmetic type.

Verified with

Code

#ifndef M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_MAX_HPP
#define M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_MAX_HPP 1

#include <algorithm>
#include <limits>
#include <optional>

namespace m1une {
namespace acted_monoid {

template <typename T, T Id = std::numeric_limits<T>::lowest()>
struct RangeUpdateRangeMax {
    using value_type = T;
    using operator_type = std::optional<T>;
    static constexpr bool commutative = true;
    static constexpr bool operator_commutative = false;

    // Value Monoid (Max)
    static constexpr value_type id() {
        return Id;
    }
    static constexpr value_type op(const value_type& a, const value_type& b) {
        return std::max(a, b);
    }

    // Operator Monoid (Update)
    static constexpr operator_type op_id() {
        return std::nullopt;
    }
    static constexpr operator_type op_comp(const operator_type& f, const operator_type& g) {
        // Prioritize the newer operation (f) over the older one (g)
        return f.has_value() ? f : g;
    }

    // Mapping
    static constexpr value_type mapping(const operator_type& f, const value_type& x) {
        if (!f.has_value() || x == id()) return x;
        return f.value();
    }
};

}  // namespace acted_monoid
}  // namespace m1une

#endif  // M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_MAX_HPP
#line 1 "acted_monoid/range_update_range_max.hpp"



#include <algorithm>
#include <limits>
#include <optional>

namespace m1une {
namespace acted_monoid {

template <typename T, T Id = std::numeric_limits<T>::lowest()>
struct RangeUpdateRangeMax {
    using value_type = T;
    using operator_type = std::optional<T>;
    static constexpr bool commutative = true;
    static constexpr bool operator_commutative = false;

    // Value Monoid (Max)
    static constexpr value_type id() {
        return Id;
    }
    static constexpr value_type op(const value_type& a, const value_type& b) {
        return std::max(a, b);
    }

    // Operator Monoid (Update)
    static constexpr operator_type op_id() {
        return std::nullopt;
    }
    static constexpr operator_type op_comp(const operator_type& f, const operator_type& g) {
        // Prioritize the newer operation (f) over the older one (g)
        return f.has_value() ? f : g;
    }

    // Mapping
    static constexpr value_type mapping(const operator_type& f, const value_type& x) {
        if (!f.has_value() || x == id()) return x;
        return f.value();
    }
};

}  // namespace acted_monoid
}  // namespace m1une
Back to top page