m1une's library

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

View on GitHub

:x: monoid/acted_monoids/range_affine_range_sum.hpp

Depends on

Required by

Verified with

Code

#ifndef M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_SUM_HPP
#define M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_SUM_HPP 1

#include "../acted_monoid.hpp"
#include "../monoid_addsz.hpp"
#include "../monoids/add_monoid.hpp"
#include "../monoids/affine_monoid.hpp"

namespace m1une {

template <typename T>
using range_affine_range_sum_monoid =
    acted_monoid<monoid_addsz<add_monoid<T>>, affine_monoid<T>,
                 [](typename affine_monoid<T>::value_type f, typename monoid_addsz<add_monoid<T>>::value_type x) {
                     // f = (a, b) is the affine transformation
                     // x = {value, size} is the data (sum and size of the range)
                     // Applying f to each element xi and summing up:
                     // sum(a*xi + b) = a * sum(xi) + b * size
                     return typename monoid_addsz<add_monoid<T>>::value_type{f.first * x.value + f.second * x.size,
                                                                             x.size};
                 }>;

}  // namespace m1une

#endif  // M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_SUM_HPP
#line 1 "monoid/acted_monoids/range_affine_range_sum.hpp"



#line 1 "monoid/acted_monoid.hpp"



#include <concepts>
#include <functional>
#include <type_traits>

#line 1 "monoid/monoid.hpp"



#line 7 "monoid/monoid.hpp"

namespace m1une {

template <typename T, auto operation, auto identity, bool commutative>
struct monoid {
    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()");

    using value_type = T;
    static constexpr auto op = operation;
    static constexpr auto id = identity;
    static constexpr bool is_commutative = commutative;
};

template <typename T>
concept Monoid = requires(typename T::value_type v) {
    typename T::value_type;
    { T::op(v, v) } -> std::same_as<typename T::value_type>;
    { T::id() } -> std::same_as<typename T::value_type>;
    { T::is_commutative } -> std::convertible_to<bool>;
};

}  // namespace m1une


#line 9 "monoid/acted_monoid.hpp"

namespace m1une {

template <Monoid Data, Monoid Act, auto mapping>
struct acted_monoid {
    using data_monoid = Data;
    using act_monoid = Act;

    using data_type = typename Data::value_type;
    using act_type = typename Act::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)");

    static constexpr auto data_op = Data::op;
    static constexpr auto data_id = Data::id;
    static constexpr bool data_is_commutative = Data::is_commutative;
    static constexpr auto act_op = Act::op;
    static constexpr auto act_id = Act::id;
    static constexpr bool act_is_commutative = Act::is_commutative;
    static constexpr auto apply = mapping;
};

template <typename T>
concept ActedMonoid = requires(typename T::data_type d, typename T::act_type a) {
    typename T::data_monoid;
    typename T::act_monoid;
    typename T::data_type;
    typename T::act_type;
    requires Monoid<typename T::data_monoid>;
    requires Monoid<typename T::act_monoid>;
    { T::apply(a, d) } -> std::same_as<typename T::data_type>;
};

}  // namespace m1une


#line 1 "monoid/monoid_addsz.hpp"



#line 5 "monoid/monoid_addsz.hpp"

#line 7 "monoid/monoid_addsz.hpp"

namespace m1une {

template <typename T>
struct value_and_size {
    T value;
    int size;
};

template <Monoid M>
using monoid_addsz = monoid<value_and_size<typename M::value_type>,
                            [](value_and_size<typename M::value_type> a, value_and_size<typename M::value_type> b) {
                                return value_and_size<typename M::value_type>{M::op(a.value, b.value), a.size + b.size};
                            },
                            []() { return value_and_size<typename M::value_type>{M::id(), 0}; }, M::is_commutative>;

}  // namespace m1une


#line 1 "monoid/monoids/add_monoid.hpp"



#line 5 "monoid/monoids/add_monoid.hpp"

namespace m1une {

template <typename T>
using add_monoid = monoid<T, [](T a, T b) { return a + b; }, []() { return T(0); }, true>;

}  // namespace m1une


#line 1 "monoid/monoids/affine_monoid.hpp"



#include <utility>

#line 7 "monoid/monoids/affine_monoid.hpp"

namespace m1une {

// Affine transformation f(x) = ax + b is represented as (a, b)
// perform f first, then g
// op(f, g)(x) = g(f(x))
template <typename T>
using affine_monoid = monoid<std::pair<T, T>,
                             [](std::pair<T, T> f, std::pair<T, T> g) {
                                 return std::pair<T, T>(f.first * g.first, f.second * g.first + g.second);
                             },
                             []() { return std::pair<T, T>(1, 0); }, false>;

}  // namespace m1une


#line 8 "monoid/acted_monoids/range_affine_range_sum.hpp"

namespace m1une {

template <typename T>
using range_affine_range_sum_monoid =
    acted_monoid<monoid_addsz<add_monoid<T>>, affine_monoid<T>,
                 [](typename affine_monoid<T>::value_type f, typename monoid_addsz<add_monoid<T>>::value_type x) {
                     // f = (a, b) is the affine transformation
                     // x = {value, size} is the data (sum and size of the range)
                     // Applying f to each element xi and summing up:
                     // sum(a*xi + b) = a * sum(xi) + b * size
                     return typename monoid_addsz<add_monoid<T>>::value_type{f.first * x.value + f.second * x.size,
                                                                             x.size};
                 }>;

}  // namespace m1une
Back to top page