Longest True Monoid
(monoid/longest_true.hpp)
- View this file on GitHub
- Last update: 2026-07-21 20:17:47+09:00
- Include:
#include "monoid/longest_true.hpp"
Overview
A monoid for finding the maximum length of a contiguous subarray where all elements satisfy a specific condition (e.g., all elements are true or equal to a target value).
Initialization
Convert your target elements into booleans and use the make method to initialize the leaf nodes.
Example
#include "ds/segtree/segtree.hpp"
#include "monoid/longest_true.hpp"
#include <iostream>
#include <vector>
using LTM = m1une::monoid::LongestTrue;
int main() {
std::vector<long long> A = {1, 3, 3, 4, 3, 3, 3, 1};
int N = A.size();
long long target = 3;
std::vector<LTM::value_type> init_data(N);
for (int i = 0; i < N; ++i) {
// Only set to true if the element matches the target
init_data[i] = LTM::make(A[i] == target);
}
m1une::ds::Segtree<LTM> seg(init_data);
auto res = seg.prod(0, N);
std::cout << "Max Length of " << target << "s: " << res.max_len << "\n"; // Output: 3
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
Verified with
Code
#ifndef M1UNE_MONOID_LONGEST_TRUE_HPP
#define M1UNE_MONOID_LONGEST_TRUE_HPP 1
#include <algorithm>
namespace m1une {
namespace monoid {
struct LongestTrueNode {
int len;
int max_len;
int l_len;
int r_len;
};
// Monoid for finding the maximum length of a contiguous subarray
// where all elements satisfy a certain condition (i.e., are "true").
struct LongestTrue {
using value_type = LongestTrueNode;
static constexpr bool commutative = false;
// The identity element represents an empty array.
static constexpr value_type id() {
return {0, 0, 0, 0};
}
// Merges two segments.
static constexpr value_type op(const value_type& a, const value_type& b) {
if (a.len == 0) return b;
if (b.len == 0) return a;
value_type res;
res.len = a.len + b.len;
res.max_len = std::max({a.max_len, b.max_len, a.r_len + b.l_len});
res.l_len = a.l_len;
if (a.len == a.l_len) res.l_len += b.l_len;
res.r_len = b.r_len;
if (b.len == b.r_len) res.r_len += a.r_len;
return res;
}
// Helper to securely create a leaf node from a boolean condition.
static constexpr value_type make(bool val) {
return {1, val ? 1 : 0, val ? 1 : 0, val ? 1 : 0};
}
};
} // namespace monoid
} // namespace m1une
#endif // M1UNE_MONOID_LONGEST_TRUE_HPP#line 1 "monoid/longest_true.hpp"
#include <algorithm>
namespace m1une {
namespace monoid {
struct LongestTrueNode {
int len;
int max_len;
int l_len;
int r_len;
};
// Monoid for finding the maximum length of a contiguous subarray
// where all elements satisfy a certain condition (i.e., are "true").
struct LongestTrue {
using value_type = LongestTrueNode;
static constexpr bool commutative = false;
// The identity element represents an empty array.
static constexpr value_type id() {
return {0, 0, 0, 0};
}
// Merges two segments.
static constexpr value_type op(const value_type& a, const value_type& b) {
if (a.len == 0) return b;
if (b.len == 0) return a;
value_type res;
res.len = a.len + b.len;
res.max_len = std::max({a.max_len, b.max_len, a.r_len + b.l_len});
res.l_len = a.l_len;
if (a.len == a.l_len) res.l_len += b.l_len;
res.r_len = b.r_len;
if (b.len == b.r_len) res.r_len += a.r_len;
return res;
}
// Helper to securely create a leaf node from a boolean condition.
static constexpr value_type make(bool val) {
return {1, val ? 1 : 0, val ? 1 : 0, val ? 1 : 0};
}
};
} // namespace monoid
} // namespace m1une