m1une's library

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

View on GitHub

:heavy_check_mark: Range Update Range Max Subarray
(acted_monoid/range_update_range_max_subarray.hpp)

Overview

An Acted Monoid for answering Maximum Contiguous Subarray Sum queries subject to Range Assignment (Set/Update) operations.

It maintains the total sum, prefix max, suffix max, and maximum subarray sum for each segment tree node. This represents a classic competitive programming pattern (e.g., CSES “Hotel Queries” variations or AtCoder Library practice).

Usage Notes

Example

using AM = m1une::acted_monoid::RangeUpdateRangeMaxSubarray<long long>;
// seg.prod(l, r).max_sub will give the maximum subarray sum in range [l, r)
// seg.apply(l, r, 5) will set all elements in [l, r) to 5.

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_SUBARRAY_HPP
#define M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_MAX_SUBARRAY_HPP 1

#include <algorithm>
#include <optional>

namespace m1une {
namespace acted_monoid {

template <typename T>
struct RangeUpdateRangeMaxSubarrayNode {
    T sum, pref, suff, max_sub;
    long long size;
};

// Acted Monoid for Range Assignment (Update) and Max Contiguous Subarray Sum.
// Note: This implementation assumes empty subarrays are allowed (max sum is at least 0).
template <typename T>
struct RangeUpdateRangeMaxSubarray {
    using value_type = RangeUpdateRangeMaxSubarrayNode<T>;
    using operator_type = std::optional<T>;
    static constexpr bool commutative = false;
    static constexpr bool operator_commutative = false;

    static constexpr value_type id() {
        return {T(0), T(0), T(0), T(0), 0};
    }

    static constexpr value_type op(const value_type& a, const value_type& b) {
        if (a.size == 0) return b;
        if (b.size == 0) return a;
        value_type res;
        res.sum = a.sum + b.sum;
        res.pref = std::max(a.pref, a.sum + b.pref);
        res.suff = std::max(b.suff, b.sum + a.suff);
        res.max_sub = std::max({a.max_sub, b.max_sub, a.suff + b.pref});
        res.size = a.size + b.size;
        return res;
    }

    static constexpr operator_type op_id() {
        return std::nullopt;
    }

    static constexpr operator_type op_comp(const operator_type& f, const operator_type& g) {
        return f ? f : g;  // left-biased because new updates override old ones
    }

    static constexpr value_type mapping(const operator_type& f, const value_type& x) {
        if (!f || x.size == 0) return x;
        value_type res;
        res.sum = (*f) * x.size;
        T max_val = std::max(T(0), res.sum);
        // If empty subarrays are NOT allowed, change to: T max_val = (*f) > 0 ? res.sum : (*f);
        res.pref = res.suff = res.max_sub = max_val;
        res.size = x.size;
        return res;
    }

    static constexpr value_type make(const T& val) {
        T max_val = std::max(T(0), val);
        return {val, max_val, max_val, max_val, 1};
    }
};

}  // namespace acted_monoid
}  // namespace m1une

#endif  // M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_MAX_SUBARRAY_HPP
#line 1 "acted_monoid/range_update_range_max_subarray.hpp"



#include <algorithm>
#include <optional>

namespace m1une {
namespace acted_monoid {

template <typename T>
struct RangeUpdateRangeMaxSubarrayNode {
    T sum, pref, suff, max_sub;
    long long size;
};

// Acted Monoid for Range Assignment (Update) and Max Contiguous Subarray Sum.
// Note: This implementation assumes empty subarrays are allowed (max sum is at least 0).
template <typename T>
struct RangeUpdateRangeMaxSubarray {
    using value_type = RangeUpdateRangeMaxSubarrayNode<T>;
    using operator_type = std::optional<T>;
    static constexpr bool commutative = false;
    static constexpr bool operator_commutative = false;

    static constexpr value_type id() {
        return {T(0), T(0), T(0), T(0), 0};
    }

    static constexpr value_type op(const value_type& a, const value_type& b) {
        if (a.size == 0) return b;
        if (b.size == 0) return a;
        value_type res;
        res.sum = a.sum + b.sum;
        res.pref = std::max(a.pref, a.sum + b.pref);
        res.suff = std::max(b.suff, b.sum + a.suff);
        res.max_sub = std::max({a.max_sub, b.max_sub, a.suff + b.pref});
        res.size = a.size + b.size;
        return res;
    }

    static constexpr operator_type op_id() {
        return std::nullopt;
    }

    static constexpr operator_type op_comp(const operator_type& f, const operator_type& g) {
        return f ? f : g;  // left-biased because new updates override old ones
    }

    static constexpr value_type mapping(const operator_type& f, const value_type& x) {
        if (!f || x.size == 0) return x;
        value_type res;
        res.sum = (*f) * x.size;
        T max_val = std::max(T(0), res.sum);
        // If empty subarrays are NOT allowed, change to: T max_val = (*f) > 0 ? res.sum : (*f);
        res.pref = res.suff = res.max_sub = max_val;
        res.size = x.size;
        return res;
    }

    static constexpr value_type make(const T& val) {
        T max_val = std::max(T(0), val);
        return {val, max_val, max_val, max_val, 1};
    }
};

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