MinCount Monoid
(monoid/min_count.hpp)
- View this file on GitHub
- Last update: 2026-07-21 20:17:47+09:00
- Include:
#include "monoid/min_count.hpp"
Overview
A monoid for finding both the minimum value and the frequency (count) of that minimum value in a range. The underlying value_type is std::pair<T, int>, where first is the value and second is the count.
Initialization
When initializing a segment tree from an array of elements, use the make(val) method to construct a leaf node with a default count of 1.
Example
#include "ds/segtree/segtree.hpp"
#include "monoid/min_count.hpp"
#include <iostream>
#include <vector>
using MinCountM = m1une::monoid::MinCount<long long>;
int main() {
std::vector<long long> A = {3, 1, 4, 1, 5, 1, 9};
int N = A.size();
std::vector<MinCountM::value_type> init_data(N);
for (int i = 0; i < N; ++i) {
init_data[i] = MinCountM::make(A[i]);
}
m1une::ds::Segtree<MinCountM> seg(init_data);
// Query the range [0, 5) -> Elements: {3, 1, 4, 1, 5}
// Minimum is 1, it appears 2 times.
auto [min_val, count] = seg.prod(0, 5);
std::cout << "Min: " << min_val << ", Count: " << count << "\n"; // Output: Min: 1, Count: 2
return 0;
}
Interface and Complexity
This is a stateless algebra tag. Generic data structures use its public
value_type, id(), and op(a, b) members. If the type also provides helpers
such as make(...) or inv(x), they are described above or in the documented
properties.
Each static operation runs in the cost of the underlying operation shown in the
properties. Scalar monoids are $O(1)$; monoids whose value_type stores several
items, permutations, or matrices scale with that stored size.
Required by
Range Add Range Min Count
(acted_monoid/range_add_range_min_count.hpp)
MaxCount Monoid
(monoid/max_count.hpp)
Verified with
verify/monoid/commutative_flags.test.cpp
verify/monoid/commutative_flags.test.cpp
verify/monoid/commutative_flags.test.cpp
Code
#ifndef M1UNE_MONOID_MIN_COUNT_HPP
#define M1UNE_MONOID_MIN_COUNT_HPP 1
#include <functional>
#include <limits>
#include <utility>
namespace m1une {
namespace monoid {
// Monoid for finding the optimal value and its frequency in a range.
// Uses a comparison functor (Compare) to determine the optimal value (default is less, i.e., minimum).
template <typename T, T Id = std::numeric_limits<T>::max(), typename Compare = std::less<T>>
struct MinCount {
using value_type = std::pair<T, int>;
static constexpr bool commutative = true;
// The identity element has the specified Id value and a count of 0.
static constexpr value_type id() {
return {Id, 0};
}
// Combines two elements, updating the optimal value and summing the counts if they are equal.
static constexpr value_type op(const value_type& a, const value_type& b) {
if (Compare()(a.first, b.first)) return a;
if (Compare()(b.first, a.first)) return b;
return {a.first, a.second + b.second};
}
// Helper to securely create a leaf node from a single value.
static constexpr value_type make(const T& val, int count = 1) {
return {val, count};
}
};
} // namespace monoid
} // namespace m1une
#endif // M1UNE_MONOID_MIN_COUNT_HPP#line 1 "monoid/min_count.hpp"
#include <functional>
#include <limits>
#include <utility>
namespace m1une {
namespace monoid {
// Monoid for finding the optimal value and its frequency in a range.
// Uses a comparison functor (Compare) to determine the optimal value (default is less, i.e., minimum).
template <typename T, T Id = std::numeric_limits<T>::max(), typename Compare = std::less<T>>
struct MinCount {
using value_type = std::pair<T, int>;
static constexpr bool commutative = true;
// The identity element has the specified Id value and a count of 0.
static constexpr value_type id() {
return {Id, 0};
}
// Combines two elements, updating the optimal value and summing the counts if they are equal.
static constexpr value_type op(const value_type& a, const value_type& b) {
if (Compare()(a.first, b.first)) return a;
if (Compare()(b.first, a.first)) return b;
return {a.first, a.second + b.second};
}
// Helper to securely create a leaf node from a single value.
static constexpr value_type make(const T& val, int count = 1) {
return {val, count};
}
};
} // namespace monoid
} // namespace m1une