#line 1 "utility/action/add_max.cpp"
/**
* @brief 区間最大値・区間加算用のヘルパークラス
* @author えびちゃん
*/
#line 1 "utility/monoid/max.cpp"
/**
* @brief max を得る演算のモノイド
* @author えびちゃん
*/
#include <algorithm>
#include <utility>
#line 1 "utility/limits.cpp"
/**
* @brief 型依存の定数
* @author えびちゃん
*/
#include <limits>
#line 11 "utility/limits.cpp"
template <typename Tp>
class limits: public std::numeric_limits<Tp> {};
template <typename T1, typename T2>
class limits<std::pair<T1, T2>> {
public:
static constexpr auto min() {
return std::make_pair(limits<T1>::min(), limits<T2>::min());
}
static constexpr auto max() {
return std::make_pair(limits<T1>::max(), limits<T2>::max());
}
};
#line 13 "utility/monoid/max.cpp"
template <typename Tp>
class max_monoid {
public:
using value_type = Tp;
private:
value_type M_x = limits<value_type>::min();
public:
max_monoid() = default; // identity
max_monoid(max_monoid const&) = default;
max_monoid(max_monoid&&) = default;
max_monoid(value_type const& x): M_x(x) {};
max_monoid(value_type&& x): M_x(std::move(x)) {};
max_monoid& operator =(max_monoid const&) = default;
max_monoid& operator =(max_monoid&&) = default;
max_monoid& operator +=(max_monoid const& that) {
M_x = std::max(M_x, that.M_x);
return *this;
}
max_monoid& operator +=(max_monoid&& that) {
M_x = std::max(M_x, std::move(that.M_x));
return *this;
}
max_monoid operator +(max_monoid const& that) const {
return max_monoid(*this) += that;
}
max_monoid operator +(max_monoid&& that) const {
return max_monoid(*this) += std::move(that);
}
value_type const& get() const { return M_x; }
};
#line 10 "utility/action/add_max.cpp"
template <typename Tp>
struct action_add_to_max {
using operand_type = max_monoid<Tp>;
using action_type = Tp;
static void act(operand_type& op, action_type const& a) {
op = operand_type(std::move(op).get() + a);
}
};