#ifndef M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_MINMAX_HPP
#define M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_MINMAX_HPP 1
#include"../acted_monoid.hpp"
#include"../monoids/affine_monoid.hpp"
#include"../monoids/minmax_monoid.hpp"namespacem1une{// Acted monoid for range affine transformations and range min/max queries.template<typenameT>usingrange_affine_range_minmax_monoid=acted_monoid<minmax_monoid<T>,affine_monoid<T>,[](typenameaffine_monoid<T>::value_typef,typenameminmax_monoid<T>::value_typex){autov1=f.first*x.first+f.second;autov2=f.first*x.second+f.second;returnstd::pair<T,T>(std::min(v1,v2),std::max(v1,v2));}>;}// namespace m1une#endif // M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_MINMAX_HPP
#line 1 "monoid/acted_monoids/range_affine_range_minmax.hpp"
#line 1 "monoid/acted_monoid.hpp"
#include<concepts>
#include<functional>
#include<type_traits>#line 1 "monoid/monoid.hpp"
#line 7 "monoid/monoid.hpp"
namespacem1une{template<typenameT,autooperation,autoidentity,boolcommutative>structmonoid{static_assert(std::is_invocable_r_v<T,decltype(operation),T,T>,"operation must work as T(T, T)");static_assert(std::is_invocable_r_v<T,decltype(identity)>,"identity must work as T()");usingvalue_type=T;staticconstexprautoop=operation;staticconstexprautoid=identity;staticconstexprboolis_commutative=commutative;};template<typenameT>conceptMonoid=requires(typenameT::value_typev){typenameT::value_type;{T::op(v,v)}->std::same_as<typenameT::value_type>;{T::id()}->std::same_as<typenameT::value_type>;{T::is_commutative}->std::convertible_to<bool>;};}// namespace m1une#line 9 "monoid/acted_monoid.hpp"
namespacem1une{template<MonoidData,MonoidAct,automapping>structacted_monoid{usingdata_monoid=Data;usingact_monoid=Act;usingdata_type=typenameData::value_type;usingact_type=typenameAct::value_type;static_assert(std::is_invocable_r_v<data_type,decltype(mapping),act_type,data_type>,"mapping must work as data_type(act_type, data_type)");staticconstexprautodata_op=Data::op;staticconstexprautodata_id=Data::id;staticconstexprbooldata_is_commutative=Data::is_commutative;staticconstexprautoact_op=Act::op;staticconstexprautoact_id=Act::id;staticconstexprboolact_is_commutative=Act::is_commutative;staticconstexprautoapply=mapping;};template<typenameT>conceptActedMonoid=requires(typenameT::data_typed,typenameT::act_typea){typenameT::data_monoid;typenameT::act_monoid;typenameT::data_type;typenameT::act_type;requiresMonoid<typenameT::data_monoid>;requiresMonoid<typenameT::act_monoid>;{T::apply(a,d)}->std::same_as<typenameT::data_type>;};}// namespace m1une#line 1 "monoid/monoids/affine_monoid.hpp"
#include<utility>#line 7 "monoid/monoids/affine_monoid.hpp"
namespacem1une{// Affine transformation f(x) = ax + b is represented as (a, b)// perform f first, then g// op(f, g)(x) = g(f(x))template<typenameT>usingaffine_monoid=monoid<std::pair<T,T>,[](std::pair<T,T>f,std::pair<T,T>g){returnstd::pair<T,T>(f.first*g.first,f.second*g.first+g.second);},[](){returnstd::pair<T,T>(1,0);},false>;}// namespace m1une#line 1 "monoid/monoids/minmax_monoid.hpp"
#include<algorithm>
#include<limits>
#line 7 "monoid/monoids/minmax_monoid.hpp"
#line 9 "monoid/monoids/minmax_monoid.hpp"
namespacem1une{// Monoid for storing both a minimum and maximum value.// The operation combines two pairs by taking the component-wise min and max.template<typenameT>usingminmax_monoid=monoid<std::pair<T,T>,[](std::pair<T,T>a,std::pair<T,T>b){returnstd::pair<T,T>(std::min(a.first,b.first),std::max(a.second,b.second));},[](){returnstd::pair<T,T>(std::numeric_limits<T>::max(),std::numeric_limits<T>::lowest());},true>;}// namespace m1une#line 7 "monoid/acted_monoids/range_affine_range_minmax.hpp"
namespacem1une{// Acted monoid for range affine transformations and range min/max queries.template<typenameT>usingrange_affine_range_minmax_monoid=acted_monoid<minmax_monoid<T>,affine_monoid<T>,[](typenameaffine_monoid<T>::value_typef,typenameminmax_monoid<T>::value_typex){autov1=f.first*x.first+f.second;autov2=f.first*x.second+f.second;returnstd::pair<T,T>(std::min(v1,v2),std::max(v1,v2));}>;}// namespace m1une