Range Update Range Sum
(acted_monoid/range_update_range_sum.hpp)
- View this file on GitHub
- Last update: 2026-07-21 20:17:47+09:00
- Include:
#include "acted_monoid/range_update_range_sum.hpp"
Overview
An acted monoid that supports range update (overwrite) operations and range sum queries.
Important Usage Note
Since the sum of a range updated to a single value $f$ becomes $f \times \text{size}$, the value_type must maintain the size of the segment. When initializing leaf nodes, use the provided helper function make(val) to correctly set the size to 1. The operator_type uses std::optional<T> to safely represent the state of “no operation”.
Example
#include "ds/segtree/lazy_segtree.hpp"
#include "acted_monoid/range_update_range_sum.hpp"
#include <iostream>
#include <vector>
using AM = m1une::acted_monoid::RangeUpdateRangeSum<long long>;
int main() {
std::vector<long long> A = {1, 2, 3, 4, 5};
int N = A.size();
std::vector<AM::value_type> init_nodes(N);
for (int i = 0; i < N; ++i) {
init_nodes[i] = AM::make(A[i]);
}
m1une::ds::LazySegtree<AM> seg(init_nodes);
// Update the range [1, 4) to 10
seg.apply(1, 4, std::optional<long long>(10));
// Get the sum of the range [0, 5)
std::cout << seg.prod(0, 5).sum << "\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_SUM_HPP
#define M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_SUM_HPP 1
#include <optional>
namespace m1une {
namespace acted_monoid {
template <typename T>
struct RangeUpdateRangeSumNode {
T sum;
long long size;
};
template <typename T>
struct RangeUpdateRangeSum {
using value_type = RangeUpdateRangeSumNode<T>;
using operator_type = std::optional<T>;
static constexpr bool commutative = true;
static constexpr bool operator_commutative = false;
static constexpr value_type id() {
return {T(0), 0};
}
static constexpr value_type op(const value_type& a, const value_type& b) {
return {a.sum + b.sum, a.size + b.size};
}
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.has_value() ? f : g;
}
static constexpr value_type mapping(const operator_type& f, const value_type& x) {
if (!f.has_value() || x.size == 0) return x;
return {f.value() * static_cast<T>(x.size), x.size};
}
static constexpr value_type make(const T& val) {
return {val, 1};
}
};
} // namespace acted_monoid
} // namespace m1une
#endif // M1UNE_ACTED_MONOID_RANGE_UPDATE_RANGE_SUM_HPP#line 1 "acted_monoid/range_update_range_sum.hpp"
#include <optional>
namespace m1une {
namespace acted_monoid {
template <typename T>
struct RangeUpdateRangeSumNode {
T sum;
long long size;
};
template <typename T>
struct RangeUpdateRangeSum {
using value_type = RangeUpdateRangeSumNode<T>;
using operator_type = std::optional<T>;
static constexpr bool commutative = true;
static constexpr bool operator_commutative = false;
static constexpr value_type id() {
return {T(0), 0};
}
static constexpr value_type op(const value_type& a, const value_type& b) {
return {a.sum + b.sum, a.size + b.size};
}
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.has_value() ? f : g;
}
static constexpr value_type mapping(const operator_type& f, const value_type& x) {
if (!f.has_value() || x.size == 0) return x;
return {f.value() * static_cast<T>(x.size), x.size};
}
static constexpr value_type make(const T& val) {
return {val, 1};
}
};
} // namespace acted_monoid
} // namespace m1une