#include "include/all.hpp"
#pragma once #include "include/actions.hpp" #include "include/adaptors.hpp" #include "include/algebraic.hpp" #include "include/convolutions.hpp" #include "include/data_structures.hpp" #include "include/geometries.hpp" #include "include/graph_theory.hpp" #include "include/hashes.hpp" #include "include/iterable.hpp" #include "include/numeric.hpp" #include "include/snippets.hpp" #include "include/views.hpp" #include "random/adaptor.hpp" #include "random/engine.hpp" #include "utility/functional.hpp" #include "utility/restrictor.hpp" #include "utility/string.hpp" #include "utility/timer.hpp" #include "global/constants.hpp" #include "structure/graph.hpp" #include "structure/grid.hpp"
#line 2 "include/all.hpp" #line 2 "include/actions.hpp" #line 2 "action/base.hpp" #include <cstddef> #include <concepts> #line 2 "internal/dev_env.hpp" #ifdef LOCAL_JUDGE inline constexpr bool DEV_ENV = true; inline constexpr bool NO_EXCEPT = false; #else inline constexpr bool DEV_ENV = false; inline constexpr bool NO_EXCEPT = true; #endif // LOCAL_JUDGE #if __cplusplus >= 202100L #define CPP20 true #define CPP23 true #elif __cplusplus >= 202002L #define CPP20 true #define CPP23 false #else #define CPP20 false #define CPP23 false #endif #line 2 "internal/types.hpp" #include <cstdint> namespace uni { namespace internal { using size_t = std::int64_t; using int128_t = __int128_t; using uint128_t = __uint128_t; } // namesapce internal } // namespace uni #line 2 "internal/dummy.hpp" namespace uni { namespace internal { struct dummy {}; } // namespace internal } // namespace uni #line 11 "action/base.hpp" #line 2 "algebraic/internal/concepts.hpp" #include <type_traits> #line 6 "algebraic/internal/concepts.hpp" #line 2 "internal/concepts.hpp" #line 6 "internal/concepts.hpp" #include <ranges> #include <limits> #include <functional> namespace uni { namespace internal { template<class R, class T> concept convertibel_range = std::convertible_to<std::ranges::range_value_t<R>, T>; template<class T, class V> concept item_or_convertible_range = std::convertible_to<T, V> || convertibel_range<T, V>; template<class Structure> concept available = requires () { typename Structure; }; template< template<class...> class Structure, class... TemplateParameters > concept available_with = available<Structure<TemplateParameters...>>; template<class T> concept arithmetic = std::is_arithmetic_v<T>; template<class T> concept pointer = std::is_pointer_v<T>; template<class T> concept structural = std::is_class_v<T>; template<class Large, class Small> concept has_double_digits_of = (std::numeric_limits<Large>::digits == 2 * std::numeric_limits<Small>::digits); template<class Large, class Small> concept has_more_digits_than = (std::numeric_limits<Large>::digits > std::numeric_limits<Small>::digits); template<class Large, class Small> concept has_or_more_digits_than = (std::numeric_limits<Large>::digits >= std::numeric_limits<Small>::digits); template<class T> concept has_static_zero = requires { T::zero; }; template<class T> concept has_static_one = requires { T::one; }; template<class L, class R = L> concept weakly_bitand_calcurable = requires (L lhs, R rhs) { lhs & rhs; }; template<class L, class R = L> concept weakly_bitor_calcurable = requires (L lhs, R rhs) { lhs | rhs; }; template<class L, class R = L> concept weakly_bitxor_calcurable = requires (L lhs, R rhs) { lhs ^ rhs; }; template<class L, class R = L> concept weakly_addable = requires (L lhs, R rhs) { lhs + rhs; }; template<class L, class R = L> concept weakly_subtractable = requires (L lhs, R rhs) { lhs - rhs; }; template<class L, class R = L> concept weakly_multipliable = requires (L lhs, R rhs) { lhs * rhs; }; template<class L, class R = L> concept weakly_divisable = requires (L lhs, R rhs) { lhs / rhs; }; template<class L, class R = L> concept weakly_remainder_calculable = requires (L lhs, R rhs) { lhs % rhs; }; template<class L, class R = L> concept weakly_bitand_assignable = requires (L lhs, R rhs) { lhs += rhs; }; template<class L, class R = L> concept weakly_bitor_assignable = requires (L lhs, R rhs) { lhs |= rhs; }; template<class L, class R = L> concept weakly_bitxor_assignable = requires (L lhs, R rhs) { lhs ^= rhs; }; template<class L, class R = L> concept weakly_addition_assignable = requires (L lhs, R rhs) { lhs += rhs; }; template<class L, class R = L> concept weakly_subtraction_assignable = requires (L lhs, R rhs) { lhs -= rhs; }; template<class L, class R = L> concept weakly_multipliation_assignalbe = requires (L lhs, R rhs) { lhs *= rhs; }; template<class L, class R = L> concept weakly_division_assignable = requires (L lhs, R rhs) { lhs /= rhs; }; template<class L, class R = L> concept weakly_remainder_assignable = requires (L lhs, R rhs) { lhs /= rhs; }; template<class L, class R = L> concept bitand_calculable = weakly_bitand_calcurable<L, R> && weakly_bitand_calcurable<std::invoke_result_t<std::bit_and<>&, L, R>, R> && weakly_bitand_calcurable<L, std::invoke_result_t<std::bit_and<>&, L, R>> && weakly_bitand_calcurable<std::invoke_result_t<std::bit_and<>&, L, R>, std::invoke_result_t<std::bit_and<>&, L, R>>; template<class L, class R = L> concept bitor_calculable = weakly_bitor_calcurable<L, R> && weakly_bitor_calcurable<std::invoke_result_t<std::bit_or<>&, L, R>, R> && weakly_bitor_calcurable<L, std::invoke_result_t<std::bit_or<>&, L, R>> && weakly_bitor_calcurable<std::invoke_result_t<std::bit_or<>&, L, R>, std::invoke_result_t<std::bit_or<>&, L, R>>; template<class L, class R = L> concept bitxor_calculable = weakly_bitxor_calcurable<L, R> && weakly_bitxor_calcurable<std::invoke_result_t<std::bit_xor<>&, L, R>, R> && weakly_bitxor_calcurable<L, std::invoke_result_t<std::bit_xor<>&, L, R>> && weakly_bitxor_calcurable<std::invoke_result_t<std::bit_xor<>&, L, R>, std::invoke_result_t<std::bit_xor<>&, L, R>>; template<class L, class R = L> concept addable = weakly_addable<L, R> && weakly_addable<std::invoke_result_t<std::plus<>&, L, R>, R> && weakly_addable<L, std::invoke_result_t<std::plus<>&, L, R>> && weakly_addable<std::invoke_result_t<std::plus<>&, L, R>, std::invoke_result_t<std::plus<>&, L, R>>; template<class L, class R = L> concept subtractable = weakly_subtractable<L, R> && weakly_subtractable<std::invoke_result_t<std::minus<>&, L, R>, R> && weakly_subtractable<L, std::invoke_result_t<std::minus<>&, L, R>> && weakly_subtractable<std::invoke_result_t<std::minus<>&, L, R>, std::invoke_result_t<std::minus<>&, L, R>>; template<class L, class R = L> concept multipliable = weakly_multipliable<L, R> && weakly_multipliable<std::invoke_result_t<std::multiplies<>&, L, R>, R> && weakly_multipliable<L, std::invoke_result_t<std::multiplies<>&, L, R>> && weakly_multipliable<std::invoke_result_t<std::multiplies<>&, L, R>, std::invoke_result_t<std::multiplies<>&, L, R>>; template<class L, class R = L> concept divisable = weakly_divisable<L, R> && weakly_divisable<std::invoke_result_t<std::divides<>&, L, R>, R> && weakly_divisable<L, std::invoke_result_t<std::divides<>&, L, R>> && weakly_divisable<std::invoke_result_t<std::divides<>&, L, R>, std::invoke_result_t<std::divides<>&, L, R>>; template<class L, class R = L> concept remainder_calculable = weakly_remainder_calculable<L, R> && weakly_remainder_calculable<std::invoke_result_t<std::modulus<>&, L, R>, R> && weakly_remainder_calculable<L, std::invoke_result_t<std::modulus<>&, L, R>> && weakly_remainder_calculable<std::invoke_result_t<std::modulus<>&, L, R>, std::invoke_result_t<std::modulus<>&, L, R>>; template<class L, class R = L> concept bitand_assignable = weakly_bitand_assignable<L, R> && weakly_bitand_assignable<std::invoke_result_t<std::bit_and<>&, L, R>, R> && weakly_bitand_assignable<L, std::invoke_result_t<std::bit_and<>&, L, R>> && weakly_bitand_assignable<std::invoke_result_t<std::bit_and<>&, L, R>, std::invoke_result_t<std::bit_and<>&, L, R>>; template<class L, class R = L> concept bitor_assignable = weakly_bitor_calcurable<L, R> && weakly_bitor_calcurable<std::invoke_result_t<std::bit_or<>&, L, R>, R> && weakly_bitor_calcurable<L, std::invoke_result_t<std::bit_or<>&, L, R>> && weakly_bitor_calcurable<std::invoke_result_t<std::bit_or<>&, L, R>, std::invoke_result_t<std::bit_or<>&, L, R>>; template<class L, class R = L> concept bitxor_assignable = weakly_bitxor_calcurable<L, R> && weakly_bitxor_calcurable<std::invoke_result_t<std::bit_xor<>&, L, R>, R> && weakly_bitxor_calcurable<L, std::invoke_result_t<std::bit_xor<>&, L, R>> && weakly_bitxor_calcurable<std::invoke_result_t<std::bit_xor<>&, L, R>, std::invoke_result_t<std::bit_xor<>&, L, R>>; template<class L, class R = L> concept addition_assignable = weakly_addition_assignable<L, R> && weakly_addition_assignable<std::remove_cvref_t<std::invoke_result_t<std::plus<>&, L, R>>, R> && weakly_addition_assignable<L, std::invoke_result_t<std::plus<>&, L, R>> && weakly_addition_assignable<std::remove_cvref_t<std::invoke_result_t<std::plus<>&, L, R>>, std::invoke_result_t<std::plus<>&, L, R>>; template<class L, class R = L> concept subtraction_assignable = weakly_subtraction_assignable<L, R> && weakly_subtraction_assignable<std::remove_cvref_t<std::invoke_result_t<std::minus<>&, L, R>>, R> && weakly_subtraction_assignable<L, std::invoke_result_t<std::minus<>&, L, R>> && weakly_subtraction_assignable<std::remove_cvref_t<std::invoke_result_t<std::minus<>&, L, R>>, std::invoke_result_t<std::minus<>&, L, R>>; template<class L, class R = L> concept multipliation_assignalbe = weakly_multipliation_assignalbe<L, R> && weakly_multipliation_assignalbe<std::remove_cvref_t<std::invoke_result_t<std::multiplies<>&, L, R>>, R> && weakly_multipliation_assignalbe<L, std::invoke_result_t<std::multiplies<>&, L, R>> && weakly_multipliation_assignalbe<std::remove_cvref_t<std::invoke_result_t<std::multiplies<>&, L, R>>, std::invoke_result_t<std::multiplies<>&, L, R>>; template<class L, class R = L> concept division_assignable = weakly_division_assignable<L, R> && weakly_division_assignable<std::remove_cvref_t<std::invoke_result_t<std::divides<>&, L, R>>, R> && weakly_division_assignable<L, std::invoke_result_t<std::divides<>&, L, R>> && weakly_division_assignable<std::remove_cvref_t<std::invoke_result_t<std::divides<>&, L, R>>, std::invoke_result_t<std::divides<>&, L, R>>; template<class L, class R = L> concept remainder_assignable = weakly_remainder_assignable<L, R> && weakly_remainder_assignable<std::remove_cvref_t<std::invoke_result_t<std::modulus<>&, L, R>>, R> && weakly_remainder_assignable<L, std::invoke_result_t<std::modulus<>&, L, R>> && weakly_remainder_assignable<std::remove_cvref_t<std::invoke_result_t<std::modulus<>&, L, R>>, std::invoke_result_t<std::modulus<>&, L, R>>; template<class T> concept weakly_incrementable = std::movable<T> && requires (T v) { { ++v } -> std::same_as<T&>; v++; }; template<class T> concept weakly_decrementable = std::movable<T> && requires (T v) { { --v } -> std::same_as<T&>; v--; }; template<class T> concept incrementable = std::regular<T> && weakly_incrementable<T> && requires (T v) { { v++ } -> std::same_as<T>; }; template<class T> concept decrementable = std::regular<T> && weakly_decrementable<T> && requires (T v) { { v-- } -> std::same_as<T>; }; template<class L, class R = L> concept weakly_arithmetic_operable = weakly_addable<L, R> && weakly_subtractable<L, R> && weakly_multipliable<L, R> && weakly_divisable<L, R>; template<class L, class R = L> concept weakly_arithmetic_operation_assignable = weakly_addition_assignable<L, R> && weakly_subtraction_assignable<L, R> && weakly_multipliation_assignalbe<L, R> && weakly_division_assignable<L, R>; template<class L, class R = L> concept arithmetic_operable = weakly_arithmetic_operable<L, R> && addable<L, R> && subtractable<L, R> && multipliable<L, R> && divisable<L, R>; template<class L, class R = L> concept arithmetic_operation_assignable = weakly_arithmetic_operation_assignable<L, R> && addition_assignable<L, R> && subtraction_assignable<L, R> && multipliation_assignalbe<L, R> && division_assignable<L, R>; template<class T> concept unary_addable = requires (T v) { { +v } -> std::same_as<T>; }; template<class T> concept unary_subtractable = requires (T v) { { -v } -> std::same_as<T>; }; template<class T> concept numeric = std::regular<T> && arithmetic_operable<T> && arithmetic_operation_assignable<T> && weakly_incrementable<T> && unary_addable<T> && unary_subtractable<T>; } // namespace internal } // namespace uni #line 9 "algebraic/internal/concepts.hpp" #line 2 "algebraic/base.hpp" #include <utility> #line 6 "algebraic/base.hpp" #line 2 "numeric/arithmetic.hpp" #include <cassert> #include <cstring> #line 7 "numeric/arithmetic.hpp" #include <string> #line 10 "numeric/arithmetic.hpp" #include <optional> #include <algorithm> #line 13 "numeric/arithmetic.hpp" #include <bit> #include <atcoder/math> #line 2 "snippet/aliases.hpp" #line 6 "snippet/aliases.hpp" #include <vector> #line 8 "snippet/aliases.hpp" #line 2 "snippet/internal/types.hpp" #line 4 "snippet/internal/types.hpp" namespace uni { using i16 = std::int16_t; using u16 = std::uint16_t; using i32 = std::int32_t; using u32 = std::uint32_t; using i64 = std::int64_t; using u64 = std::uint64_t; #ifdef __GNUC__ using i128 = __int128_t; using u128 = __uint128_t; using f128 = __float128; #endif using uint = unsigned; using ll = long long; using ull = unsigned long long; using ld = long double; } // namespace uni #line 12 "snippet/aliases.hpp" #define until(...) while(!(__VA_ARGS__)) #define CONTINUE(...) { __VA_ARGS__; continue; } #define BREAK(...) { __VA_ARGS__; break; } #define ALL(x) std::ranges::begin((x)),std::ranges::end((x)) #define RALL(x) std::ranges::rbegin((x)),std::ranges::rend((x)) #define $F first #define $S second namespace uni { constexpr char LN = '\n'; constexpr char SPC = ' '; constexpr std::pair<int,int> DIRS4[] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; constexpr std::pair<int,int> DIRS4P[] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { 0, 0 } }; constexpr std::pair<int,int> DIRS8[] = { { -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 } }; constexpr std::pair<int,int> DIRS8P[] = { { -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { 0, 0 } }; template<class T> using spair = std::pair<T,T>; } // namespace uni namespace std { using bit_reference = std::vector<bool>::reference; bit_reference operator |= (bit_reference a, const bool b) noexcept(NO_EXCEPT) { return a = a | b; } bit_reference operator &= (bit_reference a, const bool b) noexcept(NO_EXCEPT) { return a = a & b; } } #line 2 "snippet/iterations.hpp" #line 2 "macro/overload.hpp" #define $OVERLOAD2(arg0, arg1, cmd, ...) cmd #define $OVERLOAD3(arg0, arg1, arg2, cmd, ...) cmd #define $OVERLOAD4(arg0, arg1, arg2, arg3, cmd, ...) cmd #define $OVERLOAD5(arg0, arg1, arg2, arg3, arg4, cmd, ...) cmd #define $OVERLOAD6(arg0, arg1, arg2, arg3, arg4, arg5, cmd, ...) cmd #line 2 "macro/basic.hpp" #define TO_STRING_AUX(x) #x #define TO_STRING(x) TO_STRING_AUX(x) #define CONCAT_AUX(x, y) x##y #define CONCAT(x, y) CONCAT_AUX(x, y) #define UNPAREN_AUX(...) __VA_ARGS__ #define UNPAREN(...) __VA_ARGS__ #line 6 "snippet/iterations.hpp" #define LOOP(n) REPI(CONCAT(_$, __COUNTER__), n) #define REPI(i,n) for(std::remove_cvref_t<decltype(n)> i=0, CONCAT(i, $)=(n); i<CONCAT(i, $); ++i) #define REPF(i,l,r) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>> i=(l), CONCAT(i, $)=(r); i<CONCAT(i, $); ++i) #define REPIS(i,l,r,s) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>,std::remove_cvref_t<decltype(s)>> i=(l), CONCAT(i, $)=(r); i<CONCAT(i, $); i+=(s)) #define REPR(i,n) for(auto i=(n); --i>=0;) #define REPB(i,l,r) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>> i=(r), CONCAT(i, $)=(l); --i>=CONCAT(i, $);) #define REPRS(i,l,r,s) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>,std::remove_cvref_t<decltype(s)>> i=(l)+((r)-(l)-1)/(s)*(s), CONCAT(i, $)=(l); i>=CONCAT(i, $); (i-=(s))) #define REP(...) $OVERLOAD4(__VA_ARGS__, REPIS, REPF, REPI, LOOP)(__VA_ARGS__) #define REPD(...) $OVERLOAD4(__VA_ARGS__, REPRS, REPB, REPR)(__VA_ARGS__) #define FORO(i,n) for(int i=0, CONCAT(i, $)=static_cast<int>(n); i<=CONCAT(i, $); ++i) #define FORI(i,l,r) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>> i=(l), CONCAT(i, $)=(r); i<=CONCAT(i, $); ++i) #define FORIS(i,l,r,s) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>,std::remove_cvref_t<decltype(s)>> i=(l), CONCAT(i, $)=(r); i<=CONCAT(i, $); i+=(s)) #define FORRO(i,n) for(auto i=(n); i>=0; --i) #define FORR(i,l,r) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>> i=(r), CONCAT(i, $)=(l); i>=CONCAT(i, $); --i) #define FORRS(i,l,r,s) for(std::common_type_t<std::remove_cvref_t<decltype(l)>,std::remove_cvref_t<decltype(r)>,std::remove_cvref_t<decltype(s)>> i=(l)+((r)-(l))/(s)*(s), CONCAT(i, $)=(l); i>=CONCAT(i, $); i-=(s)) #define FOR(...) $OVERLOAD4(__VA_ARGS__, FORIS, FORI, FORO)(__VA_ARGS__) #define FORD(...) $OVERLOAD4(__VA_ARGS__, FORRS, FORR, FORRO)(__VA_ARGS__) #define ITR1(e0,v) for(const auto &e0 : (v)) #define ITRP1(e0,v) for(auto e0 : (v)) #define ITRR1(e0,v) for(auto &e0 : (v)) #define ITR2(e0,e1,v) for(const auto [e0, e1] : (v)) #define ITRP2(e0,e1,v) for(auto [e0, e1] : (v)) #define ITRR2(e0,e1,v) for(auto &[e0, e1] : (v)) #define ITR3(e0,e1,e2,v) for(const auto [e0, e1, e2] : (v)) #define ITRP3(e0,e1,e2,v) for(auto [e0, e1, e2] : (v)) #define ITRR3(e0,e1,e2,v) for(auto &[e0, e1, e2] : (v)) #define ITR4(e0,e1,e2,e3,v) for(const auto [e0, e1, e2, e3] : (v)) #define ITRP4(e0,e1,e2,e3,v) for(auto [e0, e1, e2, e3] : (v)) #define ITRR4(e0,e1,e2,e3,v) for(auto &[e0, e1, e2, e3] : (v)) #define ITR5(e0,e1,e2,e3,e4,v) for(const auto [e0, e1, e2, e3, e4] : (v)) #define ITRP5(e0,e1,e2,e3,e4,v) for(auto [e0, e1, e2, e3, e4] : (v)) #define ITRR5(e0,e1,e2,e3,e4,v) for(auto &[e0, e1, e2, e3, e4] : (v)) #define ITR(...) $OVERLOAD6(__VA_ARGS__, ITR5, ITR4, ITR3, ITR2, ITR1)(__VA_ARGS__) #define ITRP(...) $OVERLOAD6(__VA_ARGS__, ITRP5, ITRP4, ITRP3, ITRP2, ITRP1)(__VA_ARGS__) #define ITRR(...) $OVERLOAD6(__VA_ARGS__, ITRR5, ITRR4, ITRR3, ITRR2, ITRR1)(__VA_ARGS__) #line 21 "numeric/arithmetic.hpp" #line 25 "numeric/arithmetic.hpp" #line 2 "utility/internal/functional_base.hpp" namespace uni { template<class P> requires requires(P p) { p.first; p.second; } inline P swapped(P& pair) { return P{ pair.second, pair.first }; } } // namespace uni #line 27 "numeric/arithmetic.hpp" #line 2 "numeric/internal/number_base.hpp" #line 6 "numeric/internal/number_base.hpp" #include <string_view> #line 14 "numeric/internal/number_base.hpp" #line 18 "numeric/internal/number_base.hpp" #line 2 "adaptor/string.hpp" #line 6 "adaptor/string.hpp" #line 2 "adaptor/internal/advanced_container.hpp" #line 8 "adaptor/internal/advanced_container.hpp" #line 11 "adaptor/internal/advanced_container.hpp" #line 15 "adaptor/internal/advanced_container.hpp" #line 2 "numeric/internal/mod.hpp" #line 6 "numeric/internal/mod.hpp" namespace uni { template<class T, class R> requires internal::remainder_calculable<T, R> && internal::subtractable<T, R> && internal::unary_subtractable<T> inline T mod(T x, const R& r) noexcept(NO_EXCEPT) { if(x >= 0) return x % r; x = -x % r; if(x != 0) x = r - x; return x; } } // namespace uni #line 2 "iterable/internal/operation_base.hpp" #line 5 "iterable/internal/operation_base.hpp" #include <iterator> #include <sstream> #include <numeric> #line 11 "iterable/internal/operation_base.hpp" namespace uni { template<std::input_iterator I, std::sentinel_for<I> S> std::string join(I first, S last, const char* sep = "") noexcept(NO_EXCEPT) { if(first == last) return ""; std::ostringstream res; while(true) { res << *first; std::ranges::advance(first, 1); if(first == last) break; res << sep; } return res.str(); } template<std::ranges::input_range R> std::string join(R&& range, const char* sep = "") noexcept(NO_EXCEPT) { return join(ALL(range), sep); } template<class I, class T = std::iter_value_t<I>> requires std::sentinel_for<I, I> T sum(I first, I last, const T& base = T()) noexcept(NO_EXCEPT) { return std::accumulate(first, last, base); } template<std::ranges::input_range R, class T = std::ranges::range_value_t<R>> auto sum(R&& range, T base = T()) noexcept(NO_EXCEPT) { auto&& r = range | std::views::common; return sum(ALL(r), base); } } // namesapce uni #line 18 "adaptor/internal/advanced_container.hpp" #define UNI_ADVANCED_CONTAINER_OPERATOR(op_assign, op, concepts) \ auto& operator op_assign(const value_type& v) noexcept(NO_EXCEPT) \ requires concepts<value_type> \ { \ if constexpr(concepts<Base, value_type>) { \ this->Base::operator op_assign(v); \ } \ else { \ REP(itr, ALL(*this)) *itr op_assign v; \ } \ return *this; \ } \ \ auto& operator op_assign(const advanced_container& rhs) noexcept(NO_EXCEPT) \ requires concepts<value_type> \ { \ if constexpr(concepts<Base>) { \ this->Base::operator op_assign(*rhs._base()); \ } \ else { \ auto itr = std::ranges::begin(*this), rhs_itr = std::ranges::begin(rhs); \ auto end = std::ranges::end(*this); \ for(; itr != end; ++itr, ++rhs_itr) { \ *itr op_assign *rhs_itr; \ } \ } \ return *this; \ } \ \ template<class T = value_type> \ requires \ concepts<value_type> && \ (std::convertible_to<T, value_type> || std::same_as<T, advanced_container>) \ friend auto operator op(advanced_container lhs, const T& rhs) noexcept(NO_EXCEPT) { \ return lhs op_assign rhs; \ } \ \ template<class T = value_type> \ requires \ concepts<value_type> && std::convertible_to<T, value_type> \ friend auto operator op(const T& lhs, advanced_container rhs) noexcept(NO_EXCEPT) { \ return advanced_container(rhs.size(), lhs) op_assign rhs; \ } namespace uni { namespace internal { template<class Base> struct advanced_container : Base { private: inline Base* _base() noexcept(NO_EXCEPT) { return static_cast<Base*>(this); } inline const Base* _base() const noexcept(NO_EXCEPT) { return static_cast<const Base*>(this); } public: using Base::Base; advanced_container(const Base& base) : Base(base) {} using size_type = decltype(std::ranges::size(std::declval<Base>())); using value_type = Base::value_type; inline auto ssize() const noexcept(NO_EXCEPT) { return std::ranges::ssize(*this->_base()); } inline const auto& operator[](internal::size_t p) const noexcept(NO_EXCEPT) { p = p < 0 ? p + this->size() : p; assert(0 <= p && p < this->ssize()); return this->Base::operator[](p); } inline auto& operator[](internal::size_t p) noexcept(NO_EXCEPT) { p = p < 0 ? p + this->size() : p; assert(0 <= p && p < this->ssize()); return this->Base::operator[](p); } inline auto& fill(const value_type& v) noexcept(NO_EXCEPT) { std::ranges::fill(*this, v); return *this; } inline auto& swap(const size_type i, const size_type j) noexcept(NO_EXCEPT) { std::swap(this->operator[](i), this->operator[](j)); return *this; } inline auto& sort() noexcept(NO_EXCEPT) { std::ranges::sort(*this); return *this; } template<class F> inline auto& sort(F&& f) noexcept(NO_EXCEPT) { std::ranges::sort(*this, std::forward<F>(f)); return *this; } inline auto& stable_sort() noexcept(NO_EXCEPT) { std::ranges::stable_sort(*this); return *this; } template<class F> inline auto& stable_sort(F&& f) noexcept(NO_EXCEPT) { std::ranges::stable_sort(*this, std::forward<F>(f)); return *this; } inline auto& reverse() noexcept(NO_EXCEPT) { std::ranges::reverse(*this); return *this; } inline auto count(const value_type& v) const noexcept(NO_EXCEPT) { return std::ranges::count(*this, v); } template<class F> inline auto count_if(F&& f) const noexcept(NO_EXCEPT) { return std::ranges::count_if(*this, std::forward<F>(f)); } inline auto& resize(const size_type k) noexcept(NO_EXCEPT) { this->Base::resize(k); return *this; } inline auto& resize(const size_type k, const value_type v) noexcept(NO_EXCEPT) { this->Base::resize(k, v); return *this; } template<class F> inline auto& shuffle(F&& f) noexcept(NO_EXCEPT) { std::ranges::shuffle(*this, std::forward<F>(f)); return *this; } inline auto& unique() noexcept(NO_EXCEPT) { const auto rest = std::ranges::unique(*this); this->erase(ALL(rest)); return *this; } template<class T> inline auto binary_search(const T& v) noexcept(NO_EXCEPT) { return std::ranges::binary_search(*this, v); } template<class T> inline auto lower_bound(const T& v) noexcept(NO_EXCEPT) { return std::ranges::lower_bound(*this, v); } template<class T> inline auto upper_bound(const T& v) noexcept(NO_EXCEPT) { return std::ranges::upper_bound(*this, v); } inline auto join(const char* sep = "") noexcept(NO_EXCEPT) { return uni::join(*this, sep); } inline auto sum() const noexcept(NO_EXCEPT) { return uni::sum(*this); } inline auto max() const noexcept(NO_EXCEPT) { return std::ranges::max(*this->_base()); } inline auto min() const noexcept(NO_EXCEPT) { return std::ranges::min(*this); } inline auto begin() noexcept(NO_EXCEPT) { return std::ranges::begin(*this->_base()); } inline auto begin() const noexcept(NO_EXCEPT) { return std::ranges::begin(*this->_base()); } inline auto end() noexcept(NO_EXCEPT) { return std::ranges::end(*this->_base()); } inline auto end() const noexcept(NO_EXCEPT) { return std::ranges::end(*this->_base()); } UNI_ADVANCED_CONTAINER_OPERATOR(+=, +, internal::weakly_addition_assignable) UNI_ADVANCED_CONTAINER_OPERATOR(-=, -, internal::weakly_subtraction_assignable) UNI_ADVANCED_CONTAINER_OPERATOR(*=, *, internal::weakly_multipliation_assignalbe) UNI_ADVANCED_CONTAINER_OPERATOR(/=, /, internal::weakly_division_assignable) UNI_ADVANCED_CONTAINER_OPERATOR(%=, %, internal::weakly_remainder_assignable) UNI_ADVANCED_CONTAINER_OPERATOR(&=, &, internal::weakly_bitand_assignable) UNI_ADVANCED_CONTAINER_OPERATOR(|=, |, internal::weakly_bitor_assignable) UNI_ADVANCED_CONTAINER_OPERATOR(^=, ^, internal::weakly_bitxor_assignable) }; } // namespace internal } // namespace uni #undef UNI_ADVANCED_CONTAINER_OPERATOR #line 8 "adaptor/string.hpp" namespace uni { using string = internal::advanced_container<std::string>; } // namespace uni namespace std { template<> struct hash<uni::string> { inline auto operator()(const uni::string& key) const noexcept(NO_EXCEPT) { return std::hash<std::string>{}(static_cast<std::string>(key)); } }; } #line 2 "adaptor/vector.hpp" #line 6 "adaptor/vector.hpp" #line 9 "adaptor/vector.hpp" namespace uni { template<class... Args> using vector = internal::advanced_container<std::vector<Args...>>; } // namespace uni #line 21 "numeric/internal/number_base.hpp" namespace uni { template<std::size_t B, class T> uni::string to_base_n_string(T v) noexcept(NO_EXCEPT) { constexpr std::string_view CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static_assert(0 < B and B <= std::ranges::size(CHARS)); assert(0 <= v); uni::string res; while(v > 0) { res += CHARS[v%B]; v /= B; } std::reverse(ALL(res)); return res; } template<class T> uni::string to_base_n_string(T v, const uni::internal::size_t b) noexcept(NO_EXCEPT) { constexpr std::string_view CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; assert(1 < b && b <= std::ranges::ssize(CHARS)); assert(0 <= v); if(v == 0) return "0"; uni::string res; while(v > 0) { res += CHARS[v % b]; v /= b; } std::reverse(ALL(res)); return res; } template<class T> uni::vector<T> to_base_n_vector(T v, const uni::internal::size_t b) noexcept(NO_EXCEPT) { assert(1 < b); assert(0 <= v); uni::vector<T> res; while(v > 0) { res.push_back(v%b); v /= b; } return res; } template<std::bidirectional_iterator I, class T = typename std::iterator_traits<I>::value_type> T from_base_n_sequence(I begin, I end, const uni::internal::size_t b) noexcept(NO_EXCEPT) { assert(1 < b); if(begin == end) return 0; T res = 0; for(auto itr=end; itr-- != begin; ) { res *= b; res += *itr; } return res; } template<class T, std::forward_iterator I> T from_base_n_string(I begin, I end, const uni::internal::size_t b) noexcept(NO_EXCEPT) { assert(1 < b); if(begin == end) return 0; T sgn = 1; if(*begin == '-') { sgn = -1; ++begin; } T res = 0; for(auto itr=begin; itr != end; ++itr) { res *= b; if('0' <= *itr && *itr <= '9') { res += *itr - '0'; } else if('a' <= *itr && *itr <= 'z') { res += *itr - 'a' + 10; } else if('A' <= *itr && *itr <= 'Z'){ res += *itr - 'A' + 10; } else { assert(false); } } return res * sgn; } template<std::ranges::bidirectional_range R, class T = std::ranges::range_value_t<R>> requires std::ranges::common_range<R> T from_base_n_sequence(R range, const uni::internal::size_t b) noexcept(NO_EXCEPT) { return from_base_n_sequence(std::ranges::begin(range), std::ranges::end(range), b); } template<class T, std::ranges::bidirectional_range R> requires std::ranges::common_range<R> T from_base_n_string(R range, const uni::internal::size_t b) noexcept(NO_EXCEPT) { return from_base_n_string<T>(std::ranges::begin(range), std::ranges::end(range), b); } } // namespace uni #line 29 "numeric/arithmetic.hpp" #line 2 "iterable/operation.hpp" #line 6 "iterable/operation.hpp" #include <initializer_list> #line 9 "iterable/operation.hpp" #include <valarray> #line 17 "iterable/operation.hpp" #line 21 "iterable/operation.hpp" #line 2 "internal/type_traits.hpp" #include <iostream> #line 9 "internal/type_traits.hpp" #line 12 "internal/type_traits.hpp" namespace uni { namespace internal { template<class... Ts> struct tuple_or_pair { using type = std::tuple<Ts...>; }; template<class T, class U> struct tuple_or_pair<T,U> { using type = std::pair<T, U>; }; template <class... Ts> using tuple_or_pair_t = typename tuple_or_pair<Ts...>::type; template<class T> constexpr std::underlying_type_t<T> to_underlying(const T& v) noexcept(NO_EXCEPT) { return static_cast<std::underlying_type_t<T>>(v); } template<class T, class... Ts> using are_same = std::conjunction<std::is_same<T, Ts>...>; template<class T, class... Ts> inline constexpr bool are_same_v = are_same<T, Ts...>::value; template<class T, class... Ts> using is_same_as_any_of = std::disjunction<std::is_same<T, Ts>...>; template<class T, class... Ts> inline constexpr bool is_same_as_any_of_v = is_same_as_any_of<T, Ts...>::value; template<class T, class... Ts> concept same_as_any_of = is_same_as_any_of_v<T, Ts...>; template<class Base, class... Derived> using is_base_of_all = std::conjunction<std::is_base_of<Base, Derived>...>; template<class Base, class... Derived> inline constexpr bool is_base_of_all_v = is_base_of_all<Base, Derived...>::value; template<class Base, class... Derived> using is_base_of_any = std::disjunction<std::is_base_of<Base, Derived>...>; template<class Base, class... Derived> inline constexpr bool is_base_of_any_v = is_base_of_any<Base, Derived...>::value; template<class T> struct remove_cvref { using type = typename std::remove_cv_t<std::remove_reference_t<T>>; }; template<class T> using remove_cvref_t = typename remove_cvref<T>::type; template<class T> struct literal_operator { static constexpr const char* value = ""; }; template<> struct literal_operator<unsigned> { static constexpr const char* value = "U"; }; template<> struct literal_operator<long> { static constexpr const char* value = "L"; }; template<> struct literal_operator<unsigned long> { static constexpr const char* value = "UL"; }; template<> struct literal_operator<long long> { static constexpr const char* value = "LL"; }; template<> struct literal_operator<unsigned long long> { static constexpr const char* value = "ULL"; }; template<> struct literal_operator<float> { static constexpr const char* value = "F"; }; template<> struct literal_operator<double> { static constexpr const char* value = "D"; }; template<> struct literal_operator<long double> { static constexpr const char* value = "LD"; }; #ifdef __SIZEOF_INT128__ template<> struct literal_operator<__int128_t> { static constexpr const char* value = "LLL"; }; template<> struct literal_operator<__uint128_t> { static constexpr const char* value = "ULLL"; }; #endif template<class T> inline constexpr auto literal_operator_v = literal_operator<T>::value; template <std::size_t N, typename... Types> struct nth_type {}; template <class Head, class... Tail> struct nth_type<0, Head, Tail...> { using type = Head; }; template <std::size_t N, class Head, class... Tail> struct nth_type<N, Head, Tail...> : public nth_type<N - 1, Tail...> {}; template <std::size_t N, typename... Types> using nth_type_t = typename nth_type<N, Types...>::type; template<template <class...> class, class> struct is_template_of : std::false_type {}; template<template <class...> class Template, class... Args> struct is_template_of<Template, Template<Args...>> : std::true_type {}; template<template <class...> class Template, class Type> inline constexpr bool is_template_of_v = is_template_of<Template, Type>::value; template<class Type, template <class...> class Template> concept substituted_from = is_template_of_v<Template, Type>; template<template <class...> class Base, class Derived> struct _is_basic_tempalte_of { template<class... Ts> static constexpr std::true_type test(const Base<Ts...> *); static constexpr std::false_type test(...); using type = decltype(test(std::declval<Derived*>())); }; template<template <class...> class Base, class Derived> using is_basic_tempalte_of = _is_basic_tempalte_of<Base, Derived>::type; template<template <class...> class Base, class Derived> inline constexpr bool is_basic_tempalte_of_v = is_basic_tempalte_of<Base, Derived>::value; template<class Derived, template <class...> class Base> concept derived_from_template = is_basic_tempalte_of_v<Base, Derived>; template<class T> struct is_loggable { template<class U> static constexpr auto External(U &&v) -> decltype(_debug(v), std::true_type()); static constexpr std::false_type External(...); template<class U> static constexpr auto Member(U &&v) -> decltype(v._debug(), std::true_type()); static constexpr std::false_type Member(...); static constexpr bool value = ( decltype(External(std::declval<T>()))::value || decltype(Member(std::declval<T>()))::value ); }; template<class T> inline constexpr auto is_loggable_v = is_loggable<T>::value; template<class T> concept loggable = is_loggable_v<T>; template<class T> struct _has_iterator { template<class U> static constexpr auto ADL(U &&v) -> decltype(begin(v), end(v), std::true_type()); static constexpr std::false_type ADL(...); template<class U> static constexpr auto STL(U &&v) -> decltype(std::begin(v), std::end(v), std::true_type()); static constexpr std::false_type STL(...); template<class U> static constexpr auto Member(U &&v) -> decltype(v.begin(), v.end(), std::true_type()); static constexpr std::false_type Member(...); }; template<class T> struct has_iterator { struct ADL : decltype(_has_iterator<T>::ADL(std::declval<T>())) {}; struct STL : decltype(_has_iterator<T>::STL(std::declval<T>())) {}; struct Member : decltype(_has_iterator<T>::Member(std::declval<T>())) {}; static constexpr auto adl_v = ADL::value; static constexpr auto stl_v = STL::value; static constexpr auto member_v = Member::value; }; template<class T> struct is_iterable { static constexpr bool value = has_iterator<T>::adl_v || has_iterator<T>::stl_v || has_iterator<T>::member_v; }; template<class T> inline constexpr auto is_iterable_v = is_iterable<T>::value; template<class T> concept iterable = is_iterable_v<T>; namespace iterator_resolver { template<class T> inline constexpr auto begin(T&& v) noexcept(NO_EXCEPT) { static_assert(is_iterable_v<T>); if constexpr(has_iterator<T>::member_v) { return v.begin(); } else { // ADL using std::begin; return begin(std::forward<T>(v)); } } template<class T> inline constexpr auto end(T&& v) noexcept(NO_EXCEPT) { static_assert(is_iterable_v<T>); if constexpr(has_iterator<T>::member_v) { return v.end(); } else { // ADL using std::end; return end(std::forward<T>(v)); } } }; template<class C> using iterator_t = decltype(iterator_resolver::begin(std::declval<C&>())); template<class C> using container_size_t = decltype(std::size(std::declval<C&>())); template<bool Const, class T> using maybe_const_t = std::conditional_t<Const, const T, T>; template<class T> using with_ref = T&; template<class T> concept can_reference = requires { typename with_ref<T>; }; } // namespace internal } // namespace uni #line 2 "internal/exception.hpp" namespace uni { namespace internal { template<class... T> inline constexpr bool EXCEPTION_ON_TYPE = false; template<auto T> inline constexpr bool EXCEPTION_ON_VALUE = false; } // namespace internal } // namespace uni #line 2 "internal/iterator.hpp" #line 7 "internal/iterator.hpp" #include <variant> #include <compare> #line 10 "internal/iterator.hpp" #line 13 "internal/iterator.hpp" #line 16 "internal/iterator.hpp" namespace uni { namespace internal { template<class T> struct iterator_interface { using iterator_category = std::output_iterator_tag; using difference_type = size_t; using value_type = T; using pointer = T*; using reference = T&; // virtual T operator*() const noexcept(NO_EXCEPT) { return 0; }; }; template<class T> struct forward_iterator : iterator_interface<T> { using iterator_category = std::forward_iterator_tag; // virtual bidirectional_iterator_interface& operator++() = 0; }; template<class T> struct bidirectional_iterator_interface : forward_iterator<T> { using iterator_category = std::bidirectional_iterator_tag; // virtual bidirectional_iterator_interface& operator--() = 0; }; template<class T> struct random_access_iterator_base : bidirectional_iterator_interface<T> { using iterator_category = std::random_access_iterator_tag; using difference_type = typename bidirectional_iterator_interface<T>::difference_type; public: // virtual random_access_iterator_base& operator+=(const difference_type count) = 0; // virtual random_access_iterator_base& operator-=(const difference_type count) = 0; friend inline random_access_iterator_base operator+(random_access_iterator_base itr, const difference_type count) noexcept(NO_EXCEPT) { return itr += count, itr; } friend inline random_access_iterator_base operator-(random_access_iterator_base itr, const difference_type count) noexcept(NO_EXCEPT) { return itr -= count, itr; } }; template<class T, class Container, class Derived> struct container_iterator_interface : random_access_iterator_base<T> { using difference_type = std::make_signed_t<typename Container::size_type>; private: using derived = std::remove_cvref_t<Derived>; Container* _ref; difference_type _pos; static_assert(std::three_way_comparable<difference_type>); inline auto* _derived() noexcept(NO_EXCEPT) { return static_cast<derived*>(this); } inline const auto* _derived() const noexcept(NO_EXCEPT) { return static_cast<const derived*>(this); } public: container_iterator_interface() noexcept = default; container_iterator_interface(Container *const ref, const difference_type pos) noexcept(NO_EXCEPT) : _ref(ref), _pos(pos) {} inline auto ref() const noexcept(NO_EXCEPT) { return this->_ref; } inline auto pos() const noexcept(NO_EXCEPT) { return this->_pos; } inline auto& pos() { return this->_pos; } inline auto& operator++() noexcept(NO_EXCEPT) { return ++this->_pos, *this->_derived(); } inline auto& operator--() noexcept(NO_EXCEPT) { return --this->_pos, *this->_derived(); } inline auto operator++(int) noexcept(NO_EXCEPT) { auto res = *this->_derived(); return ++this->_pos, res; } inline auto operator--(int) noexcept(NO_EXCEPT) { auto res = *this->_derived(); return --this->_pos, res; } inline auto& operator+=(const difference_type count) noexcept(NO_EXCEPT) { return this->_pos += count, *this->_derived(); } inline auto& operator-=(const difference_type count) noexcept(NO_EXCEPT) { return this->_pos -= count, *this->_derived(); } inline auto operator*() const noexcept(NO_EXCEPT) { return this->ref()->get(this->_pos); } inline auto operator[](const difference_type count) const noexcept(NO_EXCEPT) { return *(*this->_derived() + count); } inline auto operator-(const derived& other) const noexcept(NO_EXCEPT) { return this->_pos - other._pos; } friend inline bool operator==(const derived& lhs, const derived& rhs) noexcept(NO_EXCEPT) { if(lhs.ref() == rhs.ref()) return lhs._pos == rhs._pos; return false; } friend inline std::partial_ordering operator<=>(const derived& lhs, const derived& rhs) noexcept(NO_EXCEPT) { if(lhs.ref() != rhs.ref()) return std::partial_ordering::unordered; return lhs._pos <=> rhs._pos; } }; namespace iterator_impl { template<class... Tags> using is_all_random_access_iterator = is_base_of_all<std::random_access_iterator_tag,Tags...>; template<class... Tags> using is_all_bidirectional_iterator = is_base_of_all<std::bidirectional_iterator_tag,Tags...>; template<class... Tags> using is_all_forward_iterator = is_base_of_all<std::forward_iterator_tag,Tags...>; template<class... Tags> using is_all_input_iterator = is_base_of_all<std::input_iterator_tag,Tags...>; template<class... Tags> constexpr auto _most_primitive_iterator_tag() { if constexpr(is_all_random_access_iterator<Tags...>::value) { return std::random_access_iterator_tag{}; } else if constexpr(is_all_bidirectional_iterator<Tags...>::value) { return std::bidirectional_iterator_tag{}; } else if constexpr(is_all_forward_iterator<Tags...>::value) { return std::forward_iterator_tag{}; } else { return std::input_iterator_tag{}; } } } // namespace iterator_impl template<class... Tags> using most_primitive_iterator_tag = decltype(iterator_impl::_most_primitive_iterator_tag<Tags...>()); template<class T, class = void> struct is_iterator { static constexpr bool value = false; }; template<class T> struct is_iterator<T, typename std::enable_if<!std::is_same<typename std::iterator_traits<T>::value_type, void>::value>::type> { static constexpr bool value = true; }; template<class T> inline constexpr bool is_iterator_v = is_iterator<T>::value; template<class T> using is_iterator_t = std::enable_if_t<is_iterator_v<T>>; template<class T> using iota_diff_t = std::make_signed_t<T>; } // namespace internal } // namespace uni #line 2 "internal/ranges.hpp" #line 6 "internal/ranges.hpp" #include <tuple> #line 11 "internal/ranges.hpp" namespace uni { namespace internal { template<class Range> concept resizable_range = std::ranges::range<Range> && requires (Range& r) { r.resize(0); }; template<class range> concept simple_view = std::ranges::view<range> && std::ranges::range<const range> && std::same_as<std::ranges::iterator_t<range>, std::ranges::iterator_t<const range>> && std::same_as<std::ranges::sentinel_t<range>, std::ranges::sentinel_t<const range>>; template<class... Ranges> concept zip_is_common = (sizeof...(Ranges) == 1 && (std::ranges::common_range<Ranges> && ...)) || (!(std::ranges::bidirectional_range<Ranges> && ...) && (std::ranges::common_range<Ranges> && ...)) || ((std::ranges::random_access_range<Ranges> && ...) && (std::ranges::sized_range<Ranges> && ...)); template<bool Const, class... Views> concept all_contiguous = (std::ranges::contiguous_range<maybe_const_t<Const, Views>> && ...); template<bool Const, class... Views> concept all_random_access = (std::ranges::random_access_range<maybe_const_t<Const, Views>> && ...); template<bool Const, class... Views> concept all_bidirectional = (std::ranges::bidirectional_range<maybe_const_t<Const, Views>> && ...); template<bool Const, class... Views> concept all_forward = (std::ranges::forward_range<maybe_const_t<Const, Views>> && ...); template<bool Const, class... Views> struct zip_view_iterator_category {}; template<bool Const, class... Views> requires all_forward<Const, Views...> struct zip_view_iterator_category<Const, Views...> { using iterator_category = std::input_iterator_tag; }; template<bool Const, class... Views> static auto _most_primitive_iterator_concept() noexcept(NO_EXCEPT) { if constexpr(all_random_access<Const, Views...>) return std::random_access_iterator_tag{}; else if constexpr(all_bidirectional<Const, Views...>) return std::bidirectional_iterator_tag{}; else if constexpr(all_forward<Const, Views...>) return std::forward_iterator_tag{}; else return std::input_iterator_tag{}; } template<bool Const, class... Views> using most_primitive_iterator_concept = decltype(_most_primitive_iterator_concept<Const, Views...>()); template<class Range, bool Const> using range_iterator_category = typename std::iterator_traits< std::ranges::iterator_t<maybe_const_t<Const, Range>> >::iterator_category; template<class Range> static constexpr auto _iterator_concept() noexcept(NO_EXCEPT) { if constexpr(std::ranges::random_access_range<Range>) return std::random_access_iterator_tag{}; else if constexpr(std::ranges::bidirectional_range<Range>) return std::bidirectional_iterator_tag{}; else if constexpr(std::ranges::forward_range<Range>) return std::forward_iterator_tag{}; else return std::input_iterator_tag{}; } template<class Range> using iterator_concept = decltype(_iterator_concept<Range>()); template<std::ranges::range Range> struct cached_position { constexpr bool has_value() const { return false; } constexpr std::ranges::iterator_t<Range> get(const Range&) const { __builtin_unreachable(); } constexpr void set(const Range &, const std::ranges::iterator_t<Range> &) const {} }; template<std::ranges::forward_range Range> struct cached_position<Range> : protected std::optional<std::ranges::iterator_t<Range>> { using std::optional<std::ranges::iterator_t<Range>>::optioanl; using std::optional<std::ranges::iterator_t<Range>>::has_value; constexpr std::ranges::iterator_t<Range> get(const Range&) const { assert(this->has_value()); return **this; } constexpr void set(const Range&, const std::ranges::iterator_t<Range>& itr) { assert(!this->has_value()); this->emplace(*itr); } }; template<std::ranges::random_access_range Range> requires(sizeof(std::ranges::range_difference_t<Range>) <= sizeof(std::ranges::iterator_t<Range>)) struct cached_position<Range> { private: std::ranges::range_difference_t<Range> _offset = -1; public: cached_position() = default; constexpr cached_position(const cached_position &) = default; constexpr cached_position(cached_position &&other) noexcept { *this = std::move(other); } constexpr cached_position &operator=(const cached_position &) = default; constexpr cached_position &operator=(cached_position &&other) noexcept { // Propagate the cached offset, but invalidate the source. this->_offset = other._offset; other._offset = -1; return *this; } constexpr bool has_value() const { return this->_offset >= 0; } constexpr std::ranges::iterator_t<Range> get(Range& range) const { assert(this->has_value()); return std::ranges::begin(range) + this->_offset; } constexpr void set(Range &range, const std::ranges::iterator_t<Range> &itr) { assert(!this->has_value()); this->_offset = itr - std::ranges::begin(range); } }; template<typename T, int Disc> struct absent { }; template<bool PRESENT, class T, int Disc = 0> using maybe_present_t = std::conditional_t<PRESENT, T, absent<T, Disc>>; } // namespace internal namespace views::adaptor { template<class Adaptor, class... Args> concept adaptor_invocable = requires { std::declval<Adaptor>()(std::declval<Args>()...); }; template<class Adaptor, class... Args> concept adaptor_partial_app_viable = (Adaptor::arity > 1) && (sizeof...(Args) == Adaptor::arity - 1) && (std::constructible_from<std::remove_cvref_t<Args>, Args> && ...); template<class Adaptor, class... Args> struct partial; template<class, class> struct pipe; template<class Derived> struct range_adaptor_closure {}; template<class T, class U> requires(!std::same_as<T, range_adaptor_closure<U>>) void is_range_adaptor_closure_fn(const T &, const range_adaptor_closure<U> &); template<class T> concept is_range_adaptor_closure = requires(T t) { adaptor::is_range_adaptor_closure_fn(t, t); }; template<class Self, class Range> requires is_range_adaptor_closure<Self> && adaptor_invocable<Self, Range> constexpr auto operator|(Range&& range, Self&& self) { return std::forward<Self>(self)(std::forward<Range>(range)); } template<class Lhs, class Rhs> requires is_range_adaptor_closure<Lhs> && is_range_adaptor_closure<Rhs> constexpr auto operator|(Lhs&& lhs, Rhs&& rhs) { return pipe<std::remove_cvref_t<Lhs>, std::remove_cvref_t<Rhs>>{ std::forward<Lhs>(lhs), std::forward<Rhs>(rhs)}; } template<class Derived> struct range_adaptor { template<class... Args> requires adaptor_partial_app_viable<Derived, Args...> inline constexpr auto operator()(Args&& ..._args) const noexcept(NO_EXCEPT) { return partial<Derived, std::remove_cvref_t<Args>...>{ std::forward<Args>(_args)... }; } }; template<class Adaptor> concept closure_has_simple_call_op = Adaptor::has_simple_call_op; template<class Adaptor, class... Args> concept adaptor_has_simple_extra_args = Adaptor::has_simple_extra_args || Adaptor::template has_simple_extra_args<Args...>; template<class Adaptor, class... Args> struct partial : range_adaptor_closure<partial<Adaptor, Args...>> { std::tuple<Args...> args; constexpr partial(Args... _args) noexcept(NO_EXCEPT) : args(std::move(_args)...) {} template<class Range> requires adaptor_invocable<Adaptor, Range, const Args &...> inline constexpr auto operator()(Range&& range) const & noexcept(NO_EXCEPT) { const auto forwarder = [&range](const auto &..._args) constexpr noexcept(NO_EXCEPT) { return Adaptor{}(std::forward<Range>(range), _args...); }; return std::apply(forwarder, this->args); } template<class Range> requires adaptor_invocable<Adaptor, Range, Args...> inline constexpr auto operator()(Range&& range) && noexcept(NO_EXCEPT) { const auto forwarder = [&range](auto &..._args) constexpr noexcept(NO_EXCEPT) { return Adaptor{}(std::forward<Range>(range), std::move(_args)...); }; return std::apply(forwarder, this->args); } template<class Range> inline constexpr auto operator()(Range&& range) const && = delete; }; template<class Adaptor, class Arg> struct partial<Adaptor, Arg> : range_adaptor_closure<partial<Adaptor, Arg>> { Arg arg; constexpr partial(Arg _arg) noexcept(NO_EXCEPT) : arg(std::move(_arg)) {} template<class Range> requires adaptor_invocable<Adaptor, Range, const Arg &> inline constexpr auto operator()(Range&& range) const & noexcept(NO_EXCEPT) { return Adaptor{}(std::forward<Range>(range), this->arg); } template<class Range> requires adaptor_invocable<Adaptor, Range, Arg> inline constexpr auto operator()(Range&& range) && noexcept(NO_EXCEPT) { return Adaptor{}(std::forward<Range>(range), std::move(this->arg)); } template<class Range> inline constexpr auto operator()(Range&& range) const && = delete; }; template<class Adaptor, class... Args> requires adaptor_has_simple_extra_args<Adaptor, Args...> && (std::is_trivially_copyable_v<Args> && ...) struct partial<Adaptor, Args...> : range_adaptor_closure<partial<Adaptor, Args...>> { std::tuple<Args...> args; constexpr partial(Args... _args) noexcept(NO_EXCEPT) : args(std::move(_args)...) {} template<class Range> requires adaptor_invocable<Adaptor, Range, const Args &...> inline constexpr auto operator()(Range&& range) const noexcept(NO_EXCEPT) { const auto forwarder = [&range](const auto &..._args) constexpr noexcept(NO_EXCEPT) { return Adaptor{}(std::forward<Range>(range), _args...); }; return std::apply(forwarder, this->args); } static constexpr bool has_simple_call_op = true; }; template<class Adaptor, class Arg> requires adaptor_has_simple_extra_args<Adaptor, Arg> && std::is_trivially_copyable_v<Arg> struct partial<Adaptor, Arg> : range_adaptor_closure<partial<Adaptor, Arg>> { Arg arg; constexpr partial(Arg _arg) noexcept(NO_EXCEPT) : arg(std::move(_arg)) {} template<class Range> requires adaptor_invocable<Adaptor, Range, const Arg &> inline constexpr auto operator()(Range&& range) const noexcept(NO_EXCEPT) { return Adaptor{}(std::forward<Range>(range), this->arg); } static constexpr bool has_simple_call_op = true; }; template<class Lhs, class Rhs, class Range> concept pipe_invocable = requires { std::declval<Rhs>()(std::declval<Lhs>()(std::declval<Range>())); }; template<class Lhs, class Rhs> struct pipe : range_adaptor_closure<pipe<Lhs, Rhs>> { [[no_unique_address]] Lhs lhs; [[no_unique_address]] Rhs rhs; constexpr pipe(Lhs _lhs, Rhs _rhs) noexcept(NO_EXCEPT) : lhs(std::move(_lhs)), rhs(std::move(_rhs)) {} template<class Range> requires pipe_invocable<const Lhs &, const Rhs &, Range> inline constexpr auto operator()(Range&& range) const & noexcept(NO_EXCEPT) { return rhs(lhs(std::forward<Range>(range))); } template<class Range> requires pipe_invocable<Lhs, Rhs, Range> inline constexpr auto operator()(Range&& range) && noexcept(NO_EXCEPT) { return std::move(rhs)(std::move(lhs)(std::forward<Range>(range))); } template<class Range> inline constexpr auto operator()(Range&& range) const && = delete; }; template<class Lhs, class Rhs> requires closure_has_simple_call_op<Lhs> && closure_has_simple_call_op<Rhs> struct pipe<Lhs, Rhs> : range_adaptor_closure<pipe<Lhs, Rhs>> { [[no_unique_address]] Lhs lhs; [[no_unique_address]] Rhs rhs; constexpr pipe(Lhs _lhs, Rhs _rhs) noexcept(NO_EXCEPT) : lhs(std::move(_lhs)), rhs(std::move(_rhs)) {} template<class Range> requires pipe_invocable<const Lhs &, const Rhs &, Range> inline constexpr auto operator()(Range&& range) const noexcept(NO_EXCEPT) { return rhs(lhs(std::forward<Range>(range))); } static constexpr bool has_simple_call_op = true; }; } // namespace views::adaptor } // namespace uni #line 28 "iterable/operation.hpp" #line 2 "iterable/z_array.hpp" #line 6 "iterable/z_array.hpp" #line 9 "iterable/z_array.hpp" #line 2 "adaptor/valarray.hpp" #line 11 "adaptor/valarray.hpp" #line 14 "adaptor/valarray.hpp" #line 16 "adaptor/valarray.hpp" namespace uni { template<class T> struct valarray : internal::advanced_container<std::valarray<T>> { private: using base = internal::advanced_container<std::valarray<T>>; public: using size_type = internal::size_t; using iterator = T*; using const_iterator = const T*; protected: inline bool _validate_index_in_right_open([[maybe_unused]] const size_type p) const noexcept(NO_EXCEPT) { return 0 <= p and p < this->size(); } inline bool _validate_index_in_closed([[maybe_unused]] const size_type p) const noexcept(NO_EXCEPT) { return 0 <= p and p <= this->size(); } inline bool _validate_rigth_open_interval([[maybe_unused]] const size_type l, [[maybe_unused]] const size_type r) const noexcept(NO_EXCEPT) { return 0 <= l and l <= r and r <= this->size(); } inline size_type _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->size() + p : p; } public: valarray() noexcept(NO_EXCEPT) {} explicit valarray(const std::size_t length, const T& val = T{}) noexcept(NO_EXCEPT) : base(val, length) {} template<std::input_iterator I, std::sentinel_for<I> S> valarray(I first, S last) noexcept(NO_EXCEPT) : base(std::ranges::distance(first, last)) { std::ranges::copy(first, last, std::ranges::begin(*this)); } template<class U> valarray(const U* pointer, const size_t n) noexcept(NO_EXCEPT) : base(pointer, n) {}; valarray(const std::slice_array<T>& arr) noexcept(NO_EXCEPT) : base(arr) {}; valarray(const std::gslice_array<T>& arr) noexcept(NO_EXCEPT) : base(arr) {}; valarray(const std::mask_array<T>& arr) noexcept(NO_EXCEPT) : base(arr) {}; valarray(const std::indirect_array<T>& arr) noexcept(NO_EXCEPT) : base(arr) {}; valarray(const std::initializer_list<T>& init) noexcept(NO_EXCEPT) : base(init) {} valarray(const internal::advanced_container<std::valarray<T>>& arr) noexcept(NO_EXCEPT) : base(arr) {} #ifdef __GNUC__ template<class Dom> valarray(const std::_Expr<Dom,T>& expr) noexcept(NO_EXCEPT) : base(expr) {} #endif inline auto size() const noexcept(NO_EXCEPT) { return static_cast<size_type>(this->base::size()); } inline void reserve(const size_type) noexcept(NO_EXCEPT) { /* do nothing */ } template<std::input_iterator I, std::sentinel_for<I> S> inline void assign(I first, S last) noexcept(NO_EXCEPT) { this->resize(std::ranges::distance(first, last)); std::ranges::copy(first, last, std::ranges::begin(*this)); } inline void assign(const std::size_t length, const T& val = T{}) noexcept(NO_EXCEPT) { this->base::resize(length, val); } inline void resize(const std::size_t length, const T& val = T{}) noexcept(NO_EXCEPT) { base temp = *this; this->assign(length, val); std::move(std::begin(temp), std::min(std::end(temp), std::next(std::begin(temp), length)), std::begin(*this)); } inline const T& operator[](size_type pos) const noexcept(NO_EXCEPT) { pos = this->_positivize_index(pos), assert(this->_validate_index_in_right_open(pos)); return this->base::operator[](pos); } inline T& operator[](size_type pos) noexcept(NO_EXCEPT) { pos = this->_positivize_index(pos), assert(this->_validate_index_in_right_open(pos)); return this->base::operator[](pos); } inline const T& back() const noexcept(NO_EXCEPT) { return *std::prev(this->end()); } inline T& back() noexcept(NO_EXCEPT) { return *std::prev(this->end()); } inline const T& front() const noexcept(NO_EXCEPT) { return *this->begin(); } inline T& front() noexcept(NO_EXCEPT) { return *this->begin(); } inline auto rbegin() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(std::ranges::end(*this)); } inline auto rend() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(std::ranges::begin(*this)); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(std::ranges::end(*this)); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(std::ranges::begin(*this)); } }; } // namespace uni #line 11 "iterable/z_array.hpp" namespace uni { // Thanks to: atcoder::z_algorithm template<class SizeType = internal::size_t, class Container = valarray<SizeType>> struct z_array : Container { using size_type = SizeType; template<std::input_iterator I, std::sentinel_for<I> S> z_array(I first, S last) : Container(std::ranges::distance(first, last), {}) { const size_type n = static_cast<size_type>(std::ranges::distance(first, last)); if(n == 0) return; for(size_type i = 1, j = 0; i < n; ++i) { size_type& k = this->operator[](i); k = (j + this->operator[](j) <= i) ? 0 : std::ranges::min(j + this->operator[](j) - i, this->operator[](i - j)); while(i + k < n and first[k] == first[i + k]) ++k; if(j + this->operator[](j) < i + this->operator[](i)) j = i; } *this->begin() = n; } template<std::ranges::input_range R> explicit z_array(R&& range) : z_array(ALL(range)) {} }; } // namespace uni #line 31 "iterable/operation.hpp" #line 2 "view/concat.hpp" #line 11 "view/concat.hpp" #line 18 "view/concat.hpp" namespace uni { namespace internal { namespace view_impl { template<std::ranges::input_range V0, std::ranges::input_range V1> requires std::ranges::view<V0> && std::ranges::view<V1> struct concat_view : std::ranges::view_interface<concat_view<V0, V1>> { private: V0 _b0; V1 _b1; template<bool Const> using B0 = internal::maybe_const_t<Const, V0>; template<bool Const> using B1 = internal::maybe_const_t<Const, V1>; template<bool Const> struct iterator_tag {}; template<bool Const> requires std::ranges::forward_range<B0<Const>> && std::ranges::forward_range<B1<Const>> struct iterator_tag<Const> { public: using iterator_category = uni::internal::most_primitive_iterator_tag< typename std::iterator_traits<std::ranges::iterator_t<B0<Const>>>::iterator_category, typename std::iterator_traits<std::ranges::iterator_t<B1<Const>>>::iterator_category >; }; public: template<bool> class iterator; constexpr explicit concat_view(V0 v0, V1 v1) noexcept(NO_EXCEPT) : _b0(std::move(v0)), _b1(std::move(v1)) {} inline constexpr std::pair<V0, V1> base() const & noexcept(NO_EXCEPT) requires std::copy_constructible<V0> && std::copy_constructible<V0> { return { this->_b0, this->_b1 }; } inline constexpr std::pair<V0,V1> base() && noexcept(NO_EXCEPT) { return { std::move(this->_b0), std::move(this->_b1) }; } inline constexpr auto begin() noexcept(NO_EXCEPT) requires (!internal::simple_view<V0> && !internal::simple_view<V1>) { return iterator<false>(this, std::ranges::begin(this->_b0), std::ranges::begin(this->_b1), 0); } inline constexpr auto begin() const noexcept(NO_EXCEPT) requires std::ranges::range<const V0> && std::ranges::range<const V1> { return iterator<true>(this, std::ranges::begin(this->_b0), std::ranges::begin(this->_b1), 0); } inline constexpr auto end() noexcept(NO_EXCEPT) requires (!internal::simple_view<V0> && !internal::simple_view<V1>) { if constexpr(std::ranges::common_range<V0> && std::ranges::common_range<V1>) { return iterator<false>(this, std::ranges::end(this->_b0), std::ranges::end(this->_b1), 1); } else { return std::default_sentinel; } } inline constexpr auto end() const noexcept(NO_EXCEPT) requires std::ranges::range<const V0> && std::ranges::range<const V1> { if constexpr(std::ranges::common_range<const V0> && std::ranges::common_range<const V1>) { return iterator<true>(this, std::ranges::end(this->_b0), std::ranges::end(this->_b1), 1); } else { return std::default_sentinel; } } inline constexpr auto size() noexcept(NO_EXCEPT) requires std::ranges::sized_range<V0> && std::ranges::sized_range<V1> { return static_cast<std::size_t>(std::ranges::distance(this->_b0) + std::ranges::distance(this->_b1)); } inline constexpr auto size() const noexcept(NO_EXCEPT) requires std::ranges::sized_range<const V0> && std::ranges::sized_range<const V1> { return static_cast<std::size_t>(std::ranges::distance(this->_b0) + std::ranges::distance(this->_b1)); } }; template<std::ranges::input_range V0, std::ranges::input_range V1> requires std::ranges::view<V0> && std::ranges::view<V1> template<bool Const> struct concat_view<V0, V1>::iterator : iterator_tag<Const> { private: using Parent = internal::maybe_const_t<Const, concat_view>; using B0 = concat_view::B0<Const>; using B1 = concat_view::B1<Const>; std::ranges::iterator_t<B0> _c0 = std::ranges::iterator_t<B0>(); std::ranges::iterator_t<B0> _b0 = std::ranges::iterator_t<B0>(); std::ranges::sentinel_t<B0> _e0 = std::ranges::sentinel_t<B0>(); std::ranges::iterator_t<B1> _c1 = std::ranges::iterator_t<B1>(); std::ranges::iterator_t<B1> _b1 = std::ranges::iterator_t<B1>(); std::ranges::sentinel_t<B1> _e1 = std::ranges::sentinel_t<B1>(); int _block = 0; constexpr iterator(Parent *const parent, const std::ranges::iterator_t<B0> c0, const std::ranges::iterator_t<B1> c1, const int block) noexcept(NO_EXCEPT) : _c0(std::move(c0)), _b0(std::ranges::begin(parent->_b0)), _e0(std::ranges::end(parent->_b0)), _c1(std::move(c1)), _b1(std::ranges::begin(parent->_b1)), _e1(std::ranges::end(parent->_b1)), _block(block || std::ranges::empty(parent->_b0)) {} friend concat_view; public: using difference_type = std::common_type_t<std::ranges::range_difference_t<B0>, std::ranges::range_difference_t<B1>>; using value_type = std::common_type_t<std::ranges::range_value_t<B0>, std::ranges::range_value_t<B1>>; using reference_type = std::common_reference_t<std::ranges::range_reference_t<B0>, std::ranges::range_reference_t<B1>>; using iterator_concept = most_primitive_iterator_concept<Const, V0, V1>; iterator() noexcept(NO_EXCEPT) requires std::default_initializable<std::ranges::iterator_t<B0>> && std::default_initializable<std::ranges::iterator_t<B0>> = default; constexpr iterator(iterator<!Const> itr) noexcept(NO_EXCEPT) requires Const && std::convertible_to<std::ranges::iterator_t<V0>, std::ranges::iterator_t<B0>> && std::convertible_to<std::ranges::sentinel_t<V0>, std::ranges::sentinel_t<B0>> && std::convertible_to<std::ranges::iterator_t<V1>, std::ranges::iterator_t<B1>> && std::convertible_to<std::ranges::sentinel_t<V1>, std::ranges::sentinel_t<B1>> : _c0(std::move(itr._c0)), _b0(std::move(itr._b0)), _e0(std::move(itr._e0)), _c1(std::move(itr._c0)), _b1(std::move(itr._b0)), _e1(std::move(itr._e1)), _block(itr._block) {} inline constexpr std::variant<std::ranges::iterator_t<B0>, std::ranges::iterator_t<B1>> base() && noexcept(NO_EXCEPT) { if(this->_block == 0) return std::move(this->_c0); else return std::move(this->_C1); } inline constexpr std::variant< std::reference_wrapper<const std::ranges::iterator_t<B0>>, std::reference_wrapper<const std::ranges::iterator_t<B1>> > base() const & noexcept { if(this->_block == 0) return std::move(this->_c0); else return std::move(this->_c1); } inline constexpr reference_type operator*() const noexcept(NO_EXCEPT) { if(this->_block == 0) return *this->_c0; else return *this->_c1; } inline constexpr iterator& operator++() noexcept(NO_EXCEPT) { assert(this->_c0 != this->_e0 or this->_c1 != this->_e1); if(this->_block == 0) { if(++this->_c0 == this->_e0) { this->_block = 1; assert(this->_c1 == this->_b1); } } else { ++this->_c1; } return *this; } inline constexpr void operator++(int) noexcept(NO_EXCEPT) { ++*this; } inline constexpr iterator operator++(int) noexcept(NO_EXCEPT) requires std::ranges::forward_range<B0> && std::ranges::forward_range<B1> { const auto res = *this; ++*this; return res; } inline constexpr iterator& operator--() noexcept(NO_EXCEPT) requires std::ranges::bidirectional_range<B0> && std::ranges::bidirectional_range<B1> && std::bidirectional_iterator<std::ranges::sentinel_t<B0>> { if(this->_block == 1) { if(this->_c1 == this->_b1) { this->_block = 0; this->_c0 = std::ranges::prev(this->_e0); } else { --this->_c1; } } else { --this->_c0; } return *this; } inline constexpr iterator operator--(int) noexcept(NO_EXCEPT) requires std::ranges::bidirectional_range<B0> && std::ranges::bidirectional_range<B1> { const auto res = *this; --*this; return res; } inline constexpr iterator& operator+=(const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { if(diff > 0) { if(this->_block == 0) { const auto missing = std::ranges::advance(this->_c0, diff, this->_e0); if(this->_c0 == this->_e0) { this->_block = 1; assert(this->_c1 == this->_b1); std::ranges::advance(this->_c1, missing, this->_e1); } } else { std::ranges::advance(this->_c1, diff, this->_e1); } } if(diff < 0) { if(this->_block == 1) { const auto missing = std::ranges::advance(this->_c1, diff, this->_b1); if(missing < 0) { this->_block = 0; assert(this->_c0 == this->_e0); std::ranges::advance(this->_c0, missing, this->_b0); } } else { std::ranges::advance(this->_c0, diff, this->_b0); } } return *this; } inline constexpr iterator& operator-=(const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { return *this += -diff; } inline constexpr decltype(auto) operator[](const difference_type diff) const noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { return *(*this + diff); } friend inline constexpr bool operator==(const iterator& lhs, std::default_sentinel_t) noexcept(NO_EXCEPT) { if(lhs._block == 0) return false; if(lhs._block == 1) return lhs._c1 == lhs._e1; assert(false); } friend inline constexpr bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::equality_comparable<std::ranges::iterator_t<B0>> && std::equality_comparable<std::ranges::iterator_t<B1>> { if(lhs._block != rhs._block) return false; return lhs._block == 0 ? lhs._c0 == rhs._c0 : lhs._c1 == rhs._c1; } friend inline constexpr auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { if(lhs._block != rhs._block) return lhs._block <=> rhs._block; return lhs._block == 0 ? lhs._c0 <=> rhs._c0 : lhs._c1 <=> rhs._c1; } friend inline constexpr iterator operator+(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { auto res = itr; res += diff; return res; } friend inline constexpr iterator operator+(const difference_type diff, const iterator& itr) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { return itr + diff; } friend inline constexpr iterator operator-(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<B0> && std::ranges::random_access_range<B1> { auto res = itr; res -= diff; return res; } friend inline constexpr const difference_type operator-(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::iterator_t<B0>, std::ranges::iterator_t<B0>> && std::sized_sentinel_for<std::ranges::iterator_t<B1>, std::ranges::iterator_t<B1>> { if(lhs._block == rhs._block) { return lhs._block == 0 ? std::ranges::distance(rhs._c0, lhs._c0) : std::ranges::distance(rhs._c1, lhs._c1); } if(lhs._block > rhs._block) return std::ranges::distance(rhs._c0, rhs._e0) + std::ranges::distance(lhs._b1, lhs._c1); if(lhs._block < rhs._block) return -(rhs - lhs); assert(false); } friend inline constexpr const difference_type operator-(std::default_sentinel_t, const iterator& rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::sentinel_t<B0>, std::ranges::iterator_t<B0>> && std::sized_sentinel_for<std::ranges::sentinel_t<B1>, std::ranges::iterator_t<B1>> { if(rhs._block == 0) return std::ranges::distance(rhs._c0, rhs._e0) + std::ranges::distance(rhs._b1, rhs._e1); if(rhs._block == 1) return std::ranges::distance(rhs._c1, rhs._e1); assert(false); } friend inline constexpr const difference_type operator-(const iterator& lhs, std::default_sentinel_t rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::sentinel_t<B0>, std::ranges::iterator_t<B0>> && std::sized_sentinel_for<std::ranges::sentinel_t<B1>, std::ranges::iterator_t<B1>> { return -(rhs - lhs); } friend inline constexpr std::common_reference_t< std::ranges::range_rvalue_reference_t<B0>, std::ranges::range_rvalue_reference_t<B1> > iter_move(const iterator& itr) noexcept(NO_EXCEPT) { if(itr._block == 0) return std::ranges::iter_move(itr._c0); if(itr._block == 1) return std::ranges::iter_move(itr._c1); assert(false); } friend inline constexpr void iter_swap(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::indirectly_swappable<std::ranges::iterator_t<B0>> && std::indirectly_swappable<std::ranges::iterator_t<B1>> && std::indirectly_swappable<std::ranges::iterator_t<B0>, std::ranges::iterator_t<B1>> { if(lhs._block == 0 && rhs._block == 0) std::ranges::iter_swap(lhs._c0, rhs._c0); if(lhs._block == 0 && rhs._block == 1) std::ranges::iter_swap(lhs._c0, rhs._c1); if(lhs._block == 1 && rhs._block == 0) std::ranges::iter_swap(lhs._c1, rhs._c0); if(lhs._block == 1 && rhs._block == 1) std::ranges::iter_swap(lhs._c1, rhs._c1); assert(false); } }; } // namespace view_impl } // namespace internal template<class...> struct concat_view; template<class T> struct concat_view<T> : std::views::all_t<T> { using std::views::all_t<T>::all_t; }; template<class T0, class T1> struct concat_view<T0, T1> : internal::view_impl::concat_view<std::views::all_t<T0>, std::views::all_t<T1>> { explicit concat_view(T0&& v0, T1&& v1) noexcept(NO_EXCEPT) : internal::view_impl::concat_view<std::views::all_t<T0>, std::views::all_t<T1>>(std::forward<T0>(v0), std::forward<T1>(v1)) {} }; template<class T0, class T1, class... Ts> struct concat_view<T0, T1, Ts...> : concat_view<concat_view<T0, T1>, Ts...> { explicit concat_view(T0&& v0, T1&& v1, Ts&&... vs) noexcept(NO_EXCEPT) : concat_view<concat_view<T0, T1>, Ts...>( concat_view<T0, T1>(std::forward<T0>(v0), std::forward<T1>(v1)), std::forward<Ts>(vs)... ) {} }; namespace views { namespace internal { template<class... Ts> concept can_concat_view = requires { concat_view<Ts...>(std::declval<Ts>()...); }; } // namespace internal struct Concat { template<class... Ts> requires (sizeof...(Ts) == 0 || internal::can_concat_view<Ts...>) inline constexpr auto operator() [[nodiscard]] (Ts&&... vs) const { if constexpr(sizeof...(Ts) == 0) return std::views::empty<std::nullptr_t>; else return concat_view<std::views::all_t<Ts>...>(std::forward<Ts>(vs)...); } }; inline constexpr Concat concat; } // namespace views } // namespace uni. namespace std::ranges { template<class... Views> inline constexpr bool enable_borrowed_range<uni::concat_view<Views...>> = (enable_borrowed_range<Views> && ...); } #line 2 "global/constants.hpp" #line 7 "global/constants.hpp" #include <cmath> #line 11 "global/constants.hpp" #line 14 "global/constants.hpp" #line 2 "numeric/limits.hpp" #line 6 "numeric/limits.hpp" #line 9 "numeric/limits.hpp" #line 11 "numeric/limits.hpp" namespace uni { template<class T> struct numeric_limits : std::numeric_limits<T> { static constexpr long double FLOAT_EPSILON = 1E-14; static constexpr T arithmetic_infinity() noexcept(NO_EXCEPT) { return std::numeric_limits<T>::max() / 2 - 1; } static constexpr T arithmetic_negative_infinity() noexcept(NO_EXCEPT) { return std::numeric_limits<T>::lowest() / 2 + 1; } static constexpr T arithmetic_epsilon() noexcept(NO_EXCEPT) { if constexpr(std::is_floating_point_v<T>) { return numeric_limits::FLOAT_EPSILON; } else { return 0; } } }; constexpr i32 INF32 = numeric_limits<i32>::arithmetic_infinity(); constexpr i64 INF64 = numeric_limits<i64>::arithmetic_infinity(); template<class T> constexpr T INF = numeric_limits<T>::arithmetic_infinity(); template<class T> constexpr T EPSILON = numeric_limits<T>::arithmetic_epsilon(); } // namespace uni #line 16 "global/constants.hpp" namespace uni { namespace internal { template<class T> consteval auto get_pi() { if constexpr(std::integral<T>) { return static_cast<T>(3); } else if constexpr(std::same_as<T, float>) { return M_PIf; } else if constexpr(std::same_as<T, double>) { return M_PI; } else if constexpr(std::same_as<T, ld>) { return M_PIl; } else { static_assert(EXCEPTION_ON_TYPE<T>); } } } // namespace internal template<class T = ld> constexpr auto PI = internal::get_pi<T>(); enum class comparison : std::uint8_t { equal_to, not_equal_to, equals = equal_to, eq = equal_to, under, over, or_under, or_over, less = under, more = over, less_than = under, more_than = over, not_less_than = or_over, not_more_than = or_under, leq = or_under, geq = or_over }; enum class interval_notation : std::uint8_t { right_open, left_open, open, closed, }; enum class replacement_policy : std::uint8_t { insert_sync, overwrite_sync, overwrite_async }; enum class rotation : std::int8_t { clockwise, counter_clockwise, anti_clockwise = counter_clockwise, }; enum class positional_relation : std::int8_t { clockwise, counter_clockwise, anti_clockwise = counter_clockwise, backward, forward, in, on, out, included = in, inscribed, intersecting, circumscribed, distant, }; enum class alignment : std::int8_t { left, center, right }; } // namespace uni #line 35 "iterable/operation.hpp" namespace uni { template<std::ranges::input_range R0, std::ranges::input_range R1> requires std::constructible_from< R0, std::common_type_t<std::ranges::range_size_t<R0>,std::ranges::range_size_t<R1>> > R0 concat(R0&& r0, R1&& r1) noexcept(NO_EXCEPT) { R0 res(std::ranges::size(r0) + std::ranges::size(r1)); std::ranges::copy(r0, std::ranges::begin(res)); std::ranges::copy(r1, std::ranges::next(std::ranges::begin(res), std::ranges::size(r0))); return res; } template<std::ranges::input_range R, std::ranges::input_range... Rs> R concat(R&& range, Rs&&... tails) noexcept(NO_EXCEPT) { return uni::concat(range, uni::concat(tails...)); } template<std::ranges::input_range R> requires requires(R r) { r.erase(std::ranges::unique(ALL(r)), std::ranges::end(r)); } inline auto unique(R range) noexcept(NO_EXCEPT) { std::ranges::sort(range); range.erase(std::ranges::unique(ALL(range)), std::ranges::end(range)); return range; } template< std::input_iterator I, std::sentinel_for<I> S, class T = std::iter_value_t<I> > T mex(I first, S last, const T& base = T()) noexcept(NO_EXCEPT) { std::vector<T> val(first, last); std::ranges::sort(val); { auto range = std::ranges::unique(val); val.erase(ALL(range)); } val.erase(val.begin(), std::ranges::lower_bound(val, base)); T i = 0; while(i < std::ranges::ssize(val) && val[i] == i + base) ++i; return T{i} + base; } template<std::ranges::input_range R> auto mex(R&& range, const std::ranges::range_value_t<R>& base = std::ranges::range_value_t<R>()) noexcept(NO_EXCEPT) { return mex(ALL(range), base); } template<class T> auto mex(const std::initializer_list<T> v, const T& base = T()) noexcept(NO_EXCEPT) { return mex(ALL(v), base); } template<std::input_iterator I, std::sentinel_for<I> S, class T> inline constexpr auto gcd(I first, S last) noexcept(NO_EXCEPT) { T res = T{0}; for(auto itr=first; itr!=last; ++itr) res = std::gcd(res, *itr); return res; } template<std::input_iterator I, std::sentinel_for<I> S, class T> inline constexpr auto lcm(I first, S last) noexcept(NO_EXCEPT) { T res = T{1}; for(auto itr=first; itr!=last; ++itr) res = std::lcm(res, *itr); return res; } template<std::ranges::input_range R, class T = std::ranges::range_value_t<R>> auto mex(R&& range, const T& base) noexcept(NO_EXCEPT) { return mex(ALL(range), base); } template<std::ranges::input_range R> auto gcd(R&& range) noexcept(NO_EXCEPT) { return gcd(ALL(range)); } template<std::ranges::input_range R> auto lcm(R&& range) noexcept(NO_EXCEPT) { return lcm(ALL(range)); } template<class R, std::input_iterator I, std::sentinel_for<I> S, class D> requires requires (R r, I itr) { r.emplace_back(itr, itr); } auto split(I first, S last, const D& delim = ' ') noexcept(NO_EXCEPT) { R res; for(auto itr=first, fnd=first; ; itr=std::ranges::next(fnd)) { fnd = std::find(itr, last, delim); res.emplace_back(itr, fnd); if(fnd == last) break; } return res; } template<class R, std::ranges::input_range V, class D> requires (!std::ranges::input_range<D>) auto split(V&& v, D&& d) noexcept(NO_EXCEPT) { return split<R>(ALL(v), d); } template<class R, std::ranges::input_range V, std::ranges::input_range Ds> auto split(V&& v, Ds&& ds) noexcept(NO_EXCEPT) { R res = { v }; ITR(d, ds) { R tmp; ITR(p, res) tmp = concat(tmp, split<R>(p, d)); res = std::move(tmp); } return res; } template<class R, std::ranges::input_range V, class T> auto split(V&& v, const std::initializer_list<T> ds) noexcept(NO_EXCEPT){ return split<R,V>(v, std::vector<T>(ALL(ds))); } template<std::ranges::sized_range Source, std::ranges::sized_range Qeury> auto find(Source&& source, Qeury&& query) noexcept(NO_EXCEPT) { z_array z_arr(views::concat(query, source)); const auto query_size = std::ranges::ssize(query); vector<std::ranges::iterator_t<Source>> res; { auto itr = std::ranges::begin(source); REP(i, query_size, std::ranges::size(z_arr)) { if(z_arr[i] >= query_size) res.push_back(itr); ++itr; } } return res; } template< replacement_policy POLICY, std::ranges::sized_range R, std::ranges::sized_range From, std::ranges::sized_range To > auto replaced(R&& source, From&& from, To&& to) noexcept(NO_EXCEPT) { std::remove_cvref_t<R> res; if constexpr(POLICY == replacement_policy::insert_sync) { const auto found = find(source, from); auto itr = std::ranges::begin(source); ITRR(fn, found) { std::ranges::copy(itr, fn, std::back_inserter(res)); std::ranges::copy(ALL(to), std::back_inserter(res)); itr = std::ranges::next(fn, std::ranges::size(from)); } std::ranges::copy(itr, std::ranges::end(source), std::back_inserter(res)); } else { res = source; res.resize(std::ranges::size(source) + std::ranges::size(to)); const auto found = find(res, from); auto prev = std::ranges::begin(res); ITRR(fn, found) { if constexpr(POLICY == replacement_policy::overwrite_sync) { if(prev <= fn) prev = std::ranges::copy(to, fn); } else { std::ranges::copy(to, fn); } } res.resize(std::ranges::size(source)); } return res; } template< std::ranges::sized_range R, std::ranges::sized_range From, std::ranges::sized_range To > inline auto replaced(R&& source, From&& from, To&& to) noexcept(NO_EXCEPT) { return replaced<replacement_policy::insert_sync, R, From, To>(std::forward<R>(source), std::forward<From>(from), std::forward<To>(to)); } template<alignment ALIGNMENT, internal::resizable_range R, class T = std::ranges::range_value_t<R>> auto align(R&& source, const internal::size_t size, const T& v = T()) noexcept(NO_EXCEPT) { if(std::ssize(source) >= size) return source; if(ALIGNMENT == alignment::left) { R left, right; left = source; right.resize(size - std::size(left), v); return R(ALL(uni::views::concat(left, right))); } if(ALIGNMENT == alignment::center) { R left, center, right; center = source; left.resize((size - std::size(center)) / 2, v); right.resize(size - std::size(center) - std::size(left), v); return R(ALL(uni::views::concat(left, center, right))); } if(ALIGNMENT == alignment::right) { R left, right; right = source; left.resize(size - std::size(right), v); return R(ALL(uni::views::concat(left, right))); } assert(false); } template<internal::resizable_range R, class T = std::ranges::range_value_t<R>> auto ljust(R&& source, const internal::size_t size, const T& v = T()) noexcept(NO_EXCEPT) { return align<alignment::left>(source, size, v); } template<internal::resizable_range R, class T = std::ranges::range_value_t<R>> auto cjust(R&& source, const internal::size_t size, const T& v = T()) noexcept(NO_EXCEPT) { return align<alignment::center>(source, size, v); } template<internal::resizable_range R, class T = std::ranges::range_value_t<R>> auto rjust(R&& source, const internal::size_t size, const T& v = T()) noexcept(NO_EXCEPT) { return align<alignment::right>(source, size, v); } template< class Res, std::ranges::random_access_range Target, std::ranges::forward_range Order > requires std::ranges::output_range<Res, std::ranges::range_value_t<Target>> Res ordered_by(Target&& target, Order&& order) noexcept(NO_EXCEPT) { const auto target_size = std::ranges::ssize(target); const auto order_size = std::ranges::ssize(order); Res res(order_size); { auto res_itr = std::ranges::begin(res); auto order_itr = std::ranges::begin(order); const auto order_end = std::ranges::end(std::forward<Order>(order)); for(; order_itr != order_end; ++res_itr, ++order_itr) { if constexpr(std::signed_integral<std::ranges::range_value_t<Order>>) assert(0 <= *order_itr); assert(*order_itr < target_size); *res_itr = target[*order_itr]; } } return res; } template< std::ranges::random_access_range Target, std::ranges::forward_range Order > auto ordered_by(Target&& target, Order&& order) noexcept(NO_EXCEPT) { return ordered_by<std::remove_cvref_t<Target>, Target, Order>(std::forward<Target>(target), std::forward<Order>(order)); } template<std::ranges::input_range Target, std::ranges::input_range Source> requires std::equality_comparable_with<std::ranges::range_value_t<Target>, std::ranges::range_value_t<Source>> auto is_subsequence_of(Target&& target, Source&& source) noexcept(NO_EXCEPT) { auto target_itr = std::ranges::begin(source); auto source_itr = std::ranges::begin(source); const auto target_end = std::ranges::end(source); const auto source_end = std::ranges::end(source); for(; source_itr != source_end; ++source_itr) { if(*target_itr == *source_itr) ++target_itr; } return target_itr == target_end; } template<std::ranges::input_range Target, std::ranges::input_range Source> requires std::equality_comparable_with<std::ranges::range_value_t<Target>, std::ranges::range_value_t<Source>> auto is_continuous_subsequence_of(Target&& target, Source&& source) noexcept(NO_EXCEPT) { auto found = find(source, target); return found.size() > 0; } } // namespace uni #line 31 "numeric/arithmetic.hpp" namespace uni { template<class T> inline constexpr T div_floor(const T& x, const T& d) noexcept(NO_EXCEPT) { if constexpr(std::is_integral_v<T>) { return x / d - (x % d && ((x < 0) ^ (d < 0))); } else { return std::floor(x / d); } } template<class T> inline constexpr T div_ceil(const T& x, const T& d) noexcept(NO_EXCEPT) { if constexpr(std::is_integral_v<T>) { return div_floor(x + d - 1, d); } else { return std::ceil(x / d); } } template<class T> inline constexpr T div_round(const T& x, const T& d) noexcept(NO_EXCEPT) { if constexpr(std::is_integral_v<T>) { return div_round<ld>(x, d); } else { return std::round(x / d); } } template<class T> inline constexpr std::make_signed_t<T> to_signed(const T& x) noexcept(NO_EXCEPT) { return std::bit_cast<std::make_signed_t<T>>(x); } template<class T> inline constexpr std::make_unsigned_t<T> to_unsigned(const T& x) noexcept(NO_EXCEPT) { return std::bit_cast<std::make_unsigned_t<T>>(x); } namespace internal { template<class T> inline constexpr auto perm(const T& n, const T& r) noexcept(NO_EXCEPT) { T res = 1; REP(i, r) res *= n - i; return res; } template<class T> inline constexpr auto comb(const T& n, T r) noexcept(NO_EXCEPT) { if(n < 2 * r) r = n - r; T p = 1, q = 1; REP(i, r) p *= n - i, q *= r - i; return p / q; } } // namespace internal template<class T0, std::common_with<T0> T1> inline constexpr auto perm(const T0& n, const T1& r) noexcept(NO_EXCEPT) { assert(n >= 0), assert(r >= 0); using T = std::common_type_t<T0, T1>; if(n < r) return static_cast<T>(0); return internal::perm<T>(n, r); } template<class T0, std::common_with<T0> T1> inline constexpr auto comb(const T0& n, const T1& r) noexcept(NO_EXCEPT) { assert(n >= 0), assert(r >= 0); using T = std::common_type_t<T0, T1>; if(n < r) return static_cast<T>(0); if(n == r) return static_cast<T>(1); return internal::comb<T>(n, r); } template<class T, class U, std::invocable<T, T> F = std::multiplies<>> constexpr T pow(T x, U n, F mul = F(), T one = static_cast<T>(1)) noexcept(NO_EXCEPT) { if(n == 0) return one; if(n == 1 || x == one) return x; T res = one; while(true) { if(n & 1) res = mul(res, x); x = mul(x, x); if(n == 0) return res; n >>= 1; } assert(false); } using atcoder::pow_mod; using atcoder::inv_mod; using atcoder::crt; template<class T> inline constexpr T sign(const T& x) noexcept(NO_EXCEPT) { if(x == 0) return 0; return (x > 0) ? 1 : -1; } template<class T, T FROM_MIN, T FROM_MAX, T TO_MIN, T TO_MAX> inline constexpr T mapping(const T x) { return (x - FROM_MIN) * (TO_MAX - TO_MIN) / (FROM_MAX - FROM_MIN) + TO_MIN; } template<class T> inline constexpr T mapping(const T x, const T from_min, const T from_max, const T to_min, const T to_max) { return (x - from_min) * (to_max - to_min) / (from_max - from_min) + to_min; } template<class... Args> inline constexpr std::common_type_t<Args...> min(const Args&... args) noexcept(NO_EXCEPT) { return std::min({ static_cast<std::common_type_t<Args...>>(args)... }); } template<class... Args> inline constexpr std::common_type_t<Args...> max(const Args&... args) noexcept(NO_EXCEPT) { return std::max({ static_cast<std::common_type_t<Args...>>(args)... }); } template<class T> inline constexpr T gcd(const std::initializer_list<T> args) noexcept(NO_EXCEPT) { return gcd(ALL(args)); } template<class... Args> inline constexpr std::common_type_t<Args...> gcd(const Args&... args) noexcept(NO_EXCEPT) { return gcd({ static_cast<std::common_type_t<Args...>>(args)... }); } template<class T> inline constexpr T lcm(const std::initializer_list<T> args) noexcept(NO_EXCEPT) { return lcm(ALL(args)); } template<class... Args> inline constexpr std::common_type_t<Args...> lcm(const Args&... args) noexcept(NO_EXCEPT) { return lcm({ static_cast<std::common_type_t<Args...>>(args)... }); } template<std::integral T0, std::integral T1> inline constexpr std::optional<std::common_type_t<T0, T1>> add_overflow(const T0& a, const T1& b) noexcept(NO_EXCEPT) { std::common_type_t<T0, T1> res; if(__builtin_add_overflow(a, b, &res)) return {}; return res; } template<std::integral T0, std::integral T1> inline constexpr std::optional<std::common_type_t<T0, T1>> sub_overflow(const T0& a, const T1& b) noexcept(NO_EXCEPT) { std::common_type_t<T0, T1> res; if(__builtin_sub_overflow(a, b, &res)) return {}; return res; } template<std::integral T0, std::integral T1> inline constexpr std::optional<std::common_type_t<T0, T1>> mul_overflow(const T0& a, const T1& b) noexcept(NO_EXCEPT) { std::common_type_t<T0, T1> res; if(__builtin_mul_overflow(a, b, &res)) return {}; return res; } template<std::integral T0, std::integral T1, std::integral Limit> inline auto add_clamp(const T0 x, const T1 y, const Limit inf, const Limit sup) noexcept(NO_EXCEPT) { using Common = std::common_type_t<T0, T1, Limit>; const auto res = add_overflow<Common>(x, y); if(!res) { if(x < 0 && y < 0) return inf; if(x > 0 && y > 0) return sup; assert(false); } return std::clamp<Common>(*res, inf, sup); } template<std::integral T0, std::integral T1, std::integral Limit> inline auto sub_clamp(const T0 x, const T1 y, const Limit inf, const Limit sup) noexcept(NO_EXCEPT) { using Common = std::common_type_t<T0, T1, Limit>; const auto res = sub_overflow<Common>(x, y); if(!res) { if(x < 0 && y > 0) return inf; if(x > 0 && y < 0) return sup; assert(false); } return std::clamp<Common>(*res, inf, sup); } template<std::integral T0, std::integral T1, std::integral Limit> inline auto mul_clamp(const T0 x, const T1 y, const Limit inf, const Limit sup) noexcept(NO_EXCEPT) { using Common = std::common_type_t<T0, T1, Limit>; const auto res = mul_overflow<Common>(x, y); if(!res) { if((x > 0) xor (y > 0)) return inf; else return sup; assert(false); } return std::clamp<Common>(*res, inf, sup); } template<class T> inline constexpr T sqrt_floor(const T x) noexcept(NO_EXCEPT) { return static_cast<T>(std::sqrt(static_cast<long double>(x))); } template<class T> inline constexpr T sqrt_ceil(const T x) noexcept(NO_EXCEPT) { T res = sqrt_floor(x); if constexpr(std::is_floating_point_v<T>) { while(res * res < x) res += 1; } else { while(mul_overflow(res, res).value_or(std::numeric_limits<T>::max()) < x) ++res; } return res; } template<class T, std::integral K> inline constexpr T kth_root_floor(T x, const K k) noexcept(NO_EXCEPT) { assert(x >= 0); if(std::signed_integral<K>) assert(k > 0); if(x <= 1 or k == 1) return x; constexpr auto DIGITS = std::numeric_limits<T>::digits; if(k >= DIGITS) return T{1}; if(k == 2) return sqrt_floor(x); constexpr auto MAX = std::numeric_limits<T>::max(); if(x == MAX) --x; auto pow = [&](T t, i64 p) { if(p == 0) return T{1}; T res = 1; while(p) { if(p & 1) { res = mul_overflow(res, t).value_or(MAX); } t = mul_overflow(t, t).value_or(MAX); p >>= 1; } return res; }; auto res = static_cast<T>(std::pow(x, std::nextafter(1 / static_cast<double>(k), 0))); while(pow(res + 1, k) <= x) ++res; return res; } template<std::integral T> T inline constexpr extended_gcd(const T& a, const T& b, T& x, T& y) noexcept { if(b == 0) { x = 1; y = 0; return a; } const T d = extended_gcd(b, a%b, y, x); y -= a / b * x; return d; }; template<std::integral T> std::pair<T, spair<T>> inline constexpr extended_gcd(const T& a, const T& b) noexcept { T x, y; const T d = extended_gcd(a, b, x, y); return { d, spair<T>{ x, y } }; }; template<std::integral T> std::optional<spair<T>> inline constexpr bezout_equation(const T& a, const T& b, const T& c) noexcept { if(a == 0) { if(b == 0) { if(c == 0) return spair<T>{ 0, 0 }; else { }; } if(c % b == 0) return spair<T>{ 0, c / b }; return {}; } if(b == 0) { const auto ans = bezout_equation(b, a, c); if(ans.has_value()) return swapped(ans.value()); return {}; } T x, y; const T gcd = extended_gcd(a, b, x, y); if(c % gcd != 0) return {}; const T p = c / gcd; return spair<T>{ x * p, y * p }; }; } // namespace uni #line 10 "algebraic/base.hpp" namespace uni { namespace algebraic { template<class Derived> struct scalar_multipliable { struct identity { template<std::integral Scalar> friend inline Derived operator*(const Scalar, const Derived& val) noexcept(NO_EXCEPT) { return val; } }; struct automatic { template<std::integral Scalar> friend inline Derived operator*(const Scalar k, const Derived& val) noexcept(NO_EXCEPT) { return uni::pow<Derived, Scalar, std::plus<Derived>>(val, k, {}, {}); } }; }; template<class T> struct base { using value_type = T; protected: value_type _value; public: template<class... Args> requires std::constructible_from<value_type, Args...> base(Args&&... args) noexcept(NO_EXCEPT) : _value(std::forward<Args>(args)...) {} inline explicit operator value_type() const noexcept(NO_EXCEPT) { return this->_value; } inline auto val() const noexcept(NO_EXCEPT) { return this->_value; }; inline const value_type* operator->() const noexcept(NO_EXCEPT) { return &this->_value; }; inline value_type* operator->() noexcept(NO_EXCEPT) { return &this->_value; }; friend inline auto operator<=>(const base& lhs, const base& rhs) noexcept(NO_EXCEPT) { return lhs._value <=> rhs._value; }; friend inline bool operator==(const base& lhs, const base& rhs) noexcept(NO_EXCEPT) { return lhs._value == rhs._value; } }; struct associative {}; struct commutative {}; } // namespace algebraic } // namespace uni #line 11 "algebraic/internal/concepts.hpp" namespace uni { namespace algebraic { namespace internal { template<class T> concept magma = uni::internal::addable<T> && requires { typename T::value_type; }; template<class T> concept associative = std::is_base_of_v<algebraic::associative, T>; template<class T> concept commutative = std::is_base_of_v<algebraic::commutative, T>; template<class T> concept invertible = uni::internal::unary_subtractable<T>; template<class T> concept semigroup = magma<T> && associative<T>; template<class T> concept monoid = semigroup<T> && std::default_initializable<T>; template<class T> concept group = monoid<T> && invertible<T>; } // namespace internal } // namespace algebraic } // namespace uni #line 13 "action/base.hpp" namespace uni { namespace actions { template<class operation = uni::internal::dummy> requires algebraic::internal::monoid<operation> || std::same_as<operation, uni::internal::dummy> struct base { static operation power(const operation& x, const uni::internal::size_t) noexcept(NO_EXCEPT) { return x; } }; namespace internal { template<class T> concept operatable_action = algebraic::internal::magma<typename T::operand>; template<class T> concept effective_action = algebraic::internal::magma<typename T::operation> && requires (const typename T::operation& f, const uni::internal::size_t length) { { T::power(f, length) } -> std::same_as<typename T::operation>; }; template<class T> concept operand_only_action = operatable_action<T> && (!effective_action<T>); template<class T> concept effect_only_action = effective_action<T> && (!operatable_action<T>); template<class T> concept full_action = operatable_action<T> && effective_action<T> && requires (typename T::operation f, typename T::operand v) { { T::mapping(f, v) } -> std::same_as<typename T::operand>; }; template<class T> concept action = operatable_action<T> || effective_action<T>; } // namespace internal } // namespace actions } // namespace uni #line 2 "action/helpers.hpp" #line 5 "action/helpers.hpp" #line 2 "algebraic/null.hpp" #line 5 "algebraic/null.hpp" #line 9 "algebraic/null.hpp" #line 12 "algebraic/null.hpp" namespace uni { namespace algebraic { template<class T = uni::internal::dummy> struct null : base<T>, scalar_multipliable<null<T>>::identity, associative, commutative { using base<T>::base; friend inline null operator+(const null& lhs, const null& rhs) noexcept(NO_EXCEPT) { if(lhs == null()) return rhs; return lhs; } inline null operator-() const noexcept(NO_EXCEPT) requires internal::invertible<T> { return -*this; } }; } // namespace algebraic } // namespace uni #line 2 "algebraic/helper.hpp" #line 7 "algebraic/helper.hpp" namespace uni { namespace algebraic { template<class T, auto op, auto e, class... Tags> struct helper : uni::algebraic::base<T>, uni::algebraic::scalar_multipliable<helper<T, op, e, Tags...>>::automatic, Tags... { static_assert(std::same_as<std::invoke_result_t<decltype(op), T, T>, T>); static_assert(std::same_as<std::invoke_result_t<decltype(e)>, T>); using uni::algebraic::base<T>::base; helper() : helper(e()) {} friend inline helper operator+(const helper& lhs, const helper& rhs) noexcept(NO_EXCEPT) { return op(lhs.val(), rhs.val()); } }; template<class T, auto op, auto e> using monoid_helper = helper<T, op, e, associative>; template<class T> struct make_magma { using type = null<T>; static_assert(internal::magma<type>); }; template<internal::magma T> struct make_magma<T> { using type = T; }; template<class T> using make_magma_t = typename make_magma<T>::type; } // namespace algebraic } // namespace uni #line 2 "action/null.hpp" #line 6 "action/null.hpp" #line 8 "action/null.hpp" #line 2 "algebraic/addition.hpp" #line 7 "algebraic/addition.hpp" namespace uni { namespace algebraic { template<class T> struct addition : base<T>, associative, commutative { using base<T>::base; friend inline addition operator+(const addition& lhs, const addition& rhs) noexcept(NO_EXCEPT) { return lhs.val() + rhs.val(); } template<std::integral Scalar> friend inline addition operator*(const Scalar k, const addition& rhs) noexcept(NO_EXCEPT) { return k * rhs.val(); } inline addition operator-() const noexcept(NO_EXCEPT) requires internal::invertible<T> { return -this->val(); } }; } // namespace algebraic } // namespace uni #line 11 "action/null.hpp" namespace uni { namespace actions { template<class T> struct null : base<algebraic::null<T>> { using operand = algebraic::null<T>; using operation = algebraic::null<T>; static operand mapping(const operation&, const operand& x) noexcept(NO_EXCEPT) { return x; } }; } // namespace actions } // namespace uni #line 11 "action/helpers.hpp" namespace uni { namespace actions { template<class S, auto op, auto e, class F, auto _mapping, auto composition, auto id, auto _power = nullptr> struct helper { static_assert(std::same_as<std::invoke_result_t<decltype(_mapping), F, S>, S>); // static_assert(std::same_as<std::invoke_result_t<decltype(_power), F, uni::internal::size_t>, F>); using operand = algebraic::monoid_helper<S, op, e>; using operation = algebraic::monoid_helper<F, composition, id>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return _mapping(f.val(), x.val()); } static operation power(const operation& x, [[maybe_unused]] const uni::internal::size_t length) noexcept(NO_EXCEPT) { if constexpr(_power == nullptr) return x; else return _power(x.val(), length); } }; template<class S, class F, auto _mapping, auto _power = nullptr> struct mixer { static_assert(std::same_as<std::invoke_result_t<decltype(_mapping), F, S>, S>); static_assert(std::same_as<std::invoke_result_t<decltype(_power), F, uni::internal::size_t>, F>); using operand = S; using operation = F; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return _mapping(f.val(), x.val()); } static operation power(const operation& x, [[maybe_unused]] const uni::internal::size_t length) noexcept(NO_EXCEPT) { if constexpr(_power == nullptr) return x; return _power(x.val(), length); } }; template<class S> struct amplifier { using operand = S; using operation = S; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f + x; } static operation power(const operation& x, [[maybe_unused]] const uni::internal::size_t length) noexcept(NO_EXCEPT) { return length * x; } }; template<algebraic::internal::magma Magma> struct make_operatable { struct type { using operand = Magma; }; static_assert(internal::operatable_action<type>); }; template<class T> using make_operatable_t = typename make_operatable<T>::type; template<algebraic::internal::magma Magma> struct make_effective { struct type : base<Magma> { using operation = Magma; }; static_assert(internal::effective_action<type>); }; template<class T> using make_effective_t = typename make_effective<T>::type; template<class T> struct make_full { using type = null<T>; static_assert(internal::full_action<type>); }; template<algebraic::internal::magma Magma> struct make_full<Magma> { using type = make_full<make_operatable_t<Magma>>::type; }; template<internal::full_action Action> struct make_full<Action> { using type = Action; }; template<internal::operand_only_action Action> struct make_full<Action> { using base = Action; struct type : actions::base<algebraic::null<typename base::operand::value_type>> { using operand = typename base::operand; using operation = algebraic::null<typename base::operand::value_type>; using actions::base<algebraic::null<typename base::operand::value_type>>::base; static operand mapping(const operation&, const operand& x) noexcept(NO_EXCEPT) { return x; } }; static_assert(internal::full_action<type>); }; template<internal::effect_only_action Action> struct make_full<Action> { using base = Action; struct type : base { using operand = typename base::operation; using operation = typename base::operation; using base::base; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f + x; } }; static_assert(internal::full_action<type>); }; template<class T> using make_full_t = typename make_full<T>::type; } // namespace actions } // namespace uni #line 2 "action/range_add.hpp" #line 6 "action/range_add.hpp" #line 8 "action/range_add.hpp" namespace uni { namespace actions { template<class T> struct range_add : base<algebraic::addition<T>> { using operand = algebraic::null<T>; using operation = algebraic::addition<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f.val() + x.val(); } }; static_assert(internal::full_action<range_add<int>>); } // namesapce actions } // namespace uni #line 2 "action/range_add_range_max.hpp" #line 5 "action/range_add_range_max.hpp" #line 7 "action/range_add_range_max.hpp" #line 2 "algebraic/maximum.hpp" #line 6 "algebraic/maximum.hpp" #line 9 "algebraic/maximum.hpp" namespace uni { namespace algebraic { template<class T> struct maximum : base<T>, scalar_multipliable<maximum<T>>::identity, associative, commutative { using base<T>::base; maximum() noexcept(NO_EXCEPT) : maximum(std::numeric_limits<T>::lowest()) {}; friend inline maximum operator+(const maximum& lhs, const maximum& rhs) noexcept(NO_EXCEPT) { return std::max(lhs.val(), rhs.val()); } }; } // namespace algebraic } // namespace uni #line 10 "action/range_add_range_max.hpp" namespace uni { namespace actions { template<class T> struct range_add_range_max : base<algebraic::addition<T>> { using operand = algebraic::maximum<T>; using operation = algebraic::addition<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f.val() + x.val(); } }; static_assert(internal::full_action<uni::actions::range_add_range_max<int>>); } // namespace actions } // namespace uni #line 2 "action/range_add_range_min.hpp" #line 5 "action/range_add_range_min.hpp" #line 7 "action/range_add_range_min.hpp" #line 2 "algebraic/minimum.hpp" #line 6 "algebraic/minimum.hpp" #line 9 "algebraic/minimum.hpp" namespace uni { namespace algebraic { template<class T> struct minimum : base<T>, scalar_multipliable<minimum<T>>::identity, associative, commutative { using base<T>::base; minimum() noexcept(NO_EXCEPT) : minimum(std::numeric_limits<T>::max()) {}; friend inline minimum operator+(const minimum& lhs, const minimum& rhs) noexcept(NO_EXCEPT) { return std::min(lhs.val(), rhs.val()); } }; } // namespace algebraic } // namespace uni #line 10 "action/range_add_range_min.hpp" namespace uni { namespace actions { template<class T> struct range_add_range_min : base<algebraic::addition<T>> { using operand = algebraic::minimum<T>; using operation = algebraic::addition<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f.val() + x.val(); } }; static_assert(internal::full_action<uni::actions::range_add_range_min<int>>); } // namespace actions } // namespace uni #line 2 "action/range_add_range_sum.hpp" #line 5 "action/range_add_range_sum.hpp" #line 7 "action/range_add_range_sum.hpp" #line 9 "action/range_add_range_sum.hpp" namespace uni { namespace actions { template<class T> using range_add_range_sum = amplifier<algebraic::addition<T>>; static_assert(internal::full_action<range_add_range_sum<int>>); } // namespace actions } // namespace uni #line 2 "action/range_affine_range_minmax.hpp" #line 5 "action/range_affine_range_minmax.hpp" #line 7 "action/range_affine_range_minmax.hpp" #line 2 "algebraic/minmax.hpp" #line 7 "algebraic/minmax.hpp" #line 10 "algebraic/minmax.hpp" namespace uni { namespace algebraic { template<class T> struct minmax : base<std::pair<T, T>>, scalar_multipliable<minmax<T>>::identity, associative, commutative { using base<std::pair<T, T>>::base; minmax() noexcept(NO_EXCEPT) : minmax(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()) {}; minmax(const T& v) noexcept(NO_EXCEPT) : minmax(v, v) {}; friend inline minmax operator+(const minmax& lhs, const minmax& rhs) noexcept(NO_EXCEPT) { return minmax({ std::min(lhs.val().first, rhs->first), std::max(lhs.val().second, rhs->second) }); } }; } // namespace algebraic } // namespace uni #line 2 "algebraic/affine.hpp" #line 4 "algebraic/affine.hpp" #line 7 "algebraic/affine.hpp" namespace uni { namespace algebraic { template<class T, bool REVERSE = false> struct affine : base<std::pair<T, T>>, scalar_multipliable<affine<T, REVERSE>>::automatic, associative { using base<std::pair<T, T>>::base; affine() noexcept(NO_EXCEPT) : affine({ 1, 0 }) {}; friend inline affine operator+(const affine& lhs, const affine& rhs) noexcept(NO_EXCEPT) { if constexpr(REVERSE) return affine({ lhs->first * rhs->first, lhs(rhs->second) }); return affine({ rhs->first * lhs->first, rhs(lhs->second) }); } inline auto operator()(const T& x) const noexcept(NO_EXCEPT) { return this->val().first * x + this->val().second; } }; } // namespace algebraic } // namespace uni #line 10 "action/range_affine_range_minmax.hpp" namespace uni { namespace actions { template<class T, bool REVERSE = false> struct range_affine_range_minmax : base<algebraic::affine<T, !REVERSE>> { using operand = algebraic::minmax<T>; using operation = algebraic::affine<T, !REVERSE>; static auto mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { auto res = operand({ f(x->first), f(x->second) }); if (f->first < 0) std::swap(res->first, res->second); return res; } }; static_assert(internal::full_action<range_affine_range_minmax<int>>); } // namespace actions } // namespace uni #line 2 "action/range_affine_range_sum.hpp" #line 5 "action/range_affine_range_sum.hpp" #line 7 "action/range_affine_range_sum.hpp" #line 10 "action/range_affine_range_sum.hpp" namespace uni { namespace actions { template<class T, bool REVERSE = false> struct range_affine_range_sum { using operand = algebraic::addition<T>; using operation = algebraic::affine<T, !REVERSE>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f(x.val()); } static auto power(const operation& f, const uni::internal::size_t length) noexcept(NO_EXCEPT) { return operation({ f->first, f->second * length }); } }; static_assert(internal::full_action<range_affine_range_sum<int>>); } // namespace actions } // namespace uni #line 2 "action/range_bitxor.hpp" #line 5 "action/range_bitxor.hpp" #line 8 "action/range_bitxor.hpp" #line 2 "algebraic/bit_xor.hpp" #line 5 "algebraic/bit_xor.hpp" namespace uni { namespace algebraic { template<class T> struct bit_xor : base<T>, associative, commutative { using base<T>::base; friend inline bit_xor operator+(const bit_xor& lhs, const bit_xor& rhs) noexcept(NO_EXCEPT) { return lhs.val() xor rhs.val(); } template<std::integral Scalar> friend inline bit_xor operator*(const Scalar k, const bit_xor& val) noexcept(NO_EXCEPT) { return k % 2 == 0 ? bit_xor{} : val; } inline bit_xor operator-() const noexcept(NO_EXCEPT) { return this->val(); } }; } // namespace algebraic } // namespace uni #line 10 "action/range_bitxor.hpp" namespace uni { namespace actions { template<class T> using range_bitxor = make_operatable_t<uni::algebraic::bit_xor<T>>; static_assert(internal::operand_only_action<range_bitxor<int>>); } // namespace actions } // namespace uni #line 2 "action/range_chgcd_range_gcd.hpp" #line 2 "algebraic/gcd.hpp" #line 4 "algebraic/gcd.hpp" #line 7 "algebraic/gcd.hpp" namespace uni { namespace algebraic { template<class T> struct gcd : base<T>, scalar_multipliable<gcd<T>>::identity, associative, commutative { using base<T>::base; gcd() noexcept(NO_EXCEPT) : gcd() {}; friend inline gcd operator+(const gcd& lhs, const gcd& rhs) noexcept(NO_EXCEPT) { return std::gcd(lhs.val(), rhs.val()); } }; } // namespace algebraic } // namespace uni #line 5 "action/range_chgcd_range_gcd.hpp" #line 7 "action/range_chgcd_range_gcd.hpp" namespace uni { namespace actions { template<class T> using range_chgcd_range_gcd = amplifier<uni::algebraic::gcd<T>>; static_assert(internal::full_action<range_chgcd_range_gcd<int>>); } // namespace actions } // namespace uni #line 2 "action/range_chmax_range_max.hpp" #line 5 "action/range_chmax_range_max.hpp" #line 7 "action/range_chmax_range_max.hpp" namespace uni { namespace actions { template<class T> using range_chmax_range_max = amplifier<algebraic::maximum<T>>; static_assert(internal::full_action<range_chmax_range_max<int>>); } // namespace actions } // namespace uni #line 2 "action/range_chmin_range_min.hpp" #line 5 "action/range_chmin_range_min.hpp" #line 7 "action/range_chmin_range_min.hpp" namespace uni { namespace actions { template<class T> using range_chmin_range_min = amplifier<algebraic::maximum<T>>; static_assert(internal::full_action<range_chmin_range_min<int>>); } // namespace actions } // namespace uni #line 2 "action/range_chminchmax_range_minmax.hpp" #line 5 "action/range_chminchmax_range_minmax.hpp" #line 7 "action/range_chminchmax_range_minmax.hpp" namespace uni { namespace actions { template<class T> using range_chminchmax_range_minmax = amplifier<algebraic::minmax<T>>; static_assert(internal::full_action<range_chminchmax_range_minmax<int>>); } // namespace actions } // namespace uni #line 2 "action/range_composition.hpp" #line 6 "action/range_composition.hpp" #line 8 "action/range_composition.hpp" namespace uni { namespace actions { template<class T, bool REVERSE = false> using range_composition = make_operatable_t<uni::algebraic::affine<T, REVERSE>>; static_assert(internal::operand_only_action<range_composition<int>>); } // namespace actions } // namespace uni #line 2 "action/range_flip_range_bitxor.hpp" #line 5 "action/range_flip_range_bitxor.hpp" #line 7 "action/range_flip_range_bitxor.hpp" #line 9 "action/range_flip_range_bitxor.hpp" namespace uni { namespace actions { template<class T> using range_flip_range_bitxor = amplifier<uni::algebraic::bit_xor<T>>; static_assert(internal::full_action<range_flip_range_bitxor<int>>); } // namespace actions } // namespace uni #line 2 "action/range_gcd.hpp" #line 6 "action/range_gcd.hpp" #line 8 "action/range_gcd.hpp" namespace uni { namespace actions { template<class T> using range_gcd = make_operatable_t<uni::algebraic::gcd<T>>; static_assert(internal::operand_only_action<range_gcd<int>>); } // namespace actions } // namespace uni #line 2 "action/range_max.hpp" #line 6 "action/range_max.hpp" #line 8 "action/range_max.hpp" namespace uni { namespace actions { template<class T> using range_max = make_operatable_t<uni::algebraic::maximum<T>>; static_assert(internal::operand_only_action<range_max<int>>); } // namespace actions } // namespace uni #line 2 "action/range_min.hpp" #line 6 "action/range_min.hpp" #line 8 "action/range_min.hpp" namespace uni { namespace actions { template<class T> using range_min = make_operatable_t<uni::algebraic::minimum<T>>; static_assert(internal::operand_only_action<range_min<int>>); } // namespace actions } // namespace uni #line 2 "action/range_sequence_hash.hpp" #line 5 "action/range_sequence_hash.hpp" #line 8 "action/range_sequence_hash.hpp" #line 2 "algebraic/rolling_hash.hpp" #line 5 "algebraic/rolling_hash.hpp" #line 8 "algebraic/rolling_hash.hpp" #line 10 "algebraic/rolling_hash.hpp" #line 12 "algebraic/rolling_hash.hpp" #line 2 "numeric/fast_prime.hpp" #line 6 "numeric/fast_prime.hpp" #line 2 "adaptor/set.hpp" #include <set> #include <unordered_set> #line 11 "adaptor/set.hpp" #line 15 "adaptor/set.hpp" #line 2 "utility/functional.hpp" #line 8 "utility/functional.hpp" #line 11 "utility/functional.hpp" #line 13 "utility/functional.hpp" #line 16 "utility/functional.hpp" #line 18 "utility/functional.hpp" namespace uni { namespace internal { template<class T> constexpr T plus(const T a, const T b) noexcept(NO_EXCEPT) { return std::plus<T>{}(a, b); } template<class T> constexpr T minus(const T a, const T b) noexcept(NO_EXCEPT) { return std::minus<T>{}(a, b); } template<class T> constexpr T bit_xor(const T a, const T b) noexcept(NO_EXCEPT) { return a xor b; } } // namespace internal template<class T, class U> inline auto to_optional_if_equal(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> { return v == ill ? std::optional<T>{} : std::optional<T>(v); } template<class T, class U> inline auto to_optional_if_over(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> { return v > ill ? std::optional<T>{} : std::optional<T>(v); } template<class T, class U> inline auto to_optional_if_or_over(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> { return v >= ill ? std::optional<T>{} : std::optional<T>(v); } template<class T, class U> inline auto to_optional_if_under(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> { return v < ill ? std::optional<T>{} : std::optional<T>(v); } template<class T, class U> inline auto to_optional_if_or_under(const T& v, const U& ill) noexcept(NO_EXCEPT) -> std::optional<T> { return v <= ill ? std::optional<T>{} : std::optional<T>(v); } template<class T, class F> inline auto to_optional_if(const T& v, F&& f) noexcept(NO_EXCEPT) -> decltype(f(v), std::optional<T>{}){ return f(v) ? std::optional<T>{} : std::optional<T>(v); } template<class T, class U> inline bool chmin(T &a, const U& b) noexcept(NO_EXCEPT) { return (a>b ? a=b, true : false); } template<class T, class U> inline bool chmax(T &a, const U& b) noexcept(NO_EXCEPT) { return (a<b ? a=b, true : false); } template<class T, class... Ts> inline bool chmin(T &a, Ts... b) noexcept(NO_EXCEPT) { return chmin(a, min(b...)); } template<class T, class... Ts> inline bool chmax(T &a, Ts... b) noexcept(NO_EXCEPT) { return chmax(a, max(b...)); } template<class... Ts> inline constexpr std::common_type_t<Ts...> tuple_sum(const std::tuple<Ts...>& tuple, const std::common_type_t<Ts...>& base = std::common_type_t<Ts...>()) noexcept(NO_EXCEPT) { std::common_type_t<Ts...> res = base; tuple_for_each(tuple, [&](const auto& v) constexpr { res += v; }); return res; } template<class... Ts> inline constexpr std::common_type_t<Ts...> min_element(const std::tuple<Ts...>& tuple) noexcept(NO_EXCEPT) { return std::apply([&](auto&&... v) constexpr { return min(v...); }, tuple); } template<class... Ts> inline constexpr std::common_type_t<Ts...> max_element(const std::tuple<Ts...>& tuple) noexcept(NO_EXCEPT) {; return std::apply([&](auto&&... v) constexpr { return max(v...); }, tuple); } template<interval_notation INTERVAL, class T0, class T1, class T2> inline constexpr bool in_range(const T0& x, const T1& l, const T2& r) noexcept(NO_EXCEPT) { if constexpr(INTERVAL == interval_notation::right_open) return l <= x and x < r; else if constexpr(INTERVAL == interval_notation::left_open) return l < x and x <= r; else if constexpr(INTERVAL == interval_notation::open) return l < x and x < r; return l <= x and x <= r; } template<class F, class Tuple> constexpr void tuple_for_each(F&& f, Tuple&& tuple) { std::apply( [&]<class... Ts>(Ts&&... elems) { (std::invoke(f, std::forward<Ts>(elems)), ...); }, std::forward<Tuple>(tuple) ); } template<class F, class Tuple> constexpr auto tuple_transform(F&& f, Tuple&& tuple) { return std::apply( [&]<class...Ts>(Ts&&... elems) { return internal::tuple_or_pair_t<std::invoke_result_t<F&,Ts>...>( std::invoke(f, std::forward<Ts>(elems))... ); }, std::forward<Tuple>(tuple) ); } } // namespace uni #line 17 "adaptor/set.hpp" namespace uni { namespace internal { template<class Set> struct set_wrapper : Set { using Set::Set; using value_type = typename Set::value_type; using size_type = internal::size_t; template<class Key> auto remove(Key&& key) noexcept(NO_EXCEPT) { return this->extract(std::forward<Key>(key)); } inline auto ssize() const noexcept(NO_EXCEPT) { return std::ranges::ssize(*this); } inline auto min_element() const noexcept(NO_EXCEPT) { return this->begin(); } inline auto max_element() const noexcept(NO_EXCEPT) { return std::ranges::prev(this->end()); } inline auto min() const noexcept(NO_EXCEPT) { return *this->begin(); } inline auto max() const noexcept(NO_EXCEPT) { return *std::ranges::prev(this->end()); } inline auto& pop_min() noexcept(NO_EXCEPT) { this->erase(this->begin()); return *this; } inline auto& pop_max() noexcept(NO_EXCEPT) { this->erase(std::ranges::prev(this->end())); return *this; } inline auto kth_smallest_element(const size_type k) const noexcept(NO_EXCEPT) { return std::ranges::next(this->begin(), k); } inline auto kth_largest_element(const size_type k) const noexcept(NO_EXCEPT) { return std::ranges::prev(this->end(), k + 1); } inline auto kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { return *std::ranges::next(this->begin(), k); } inline auto kth_largest(const size_type k) const noexcept(NO_EXCEPT) { return *std::ranges::prev(this->end(), k + 1); } inline auto& pop_kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { return this->erase(std::ranges::next(this->begin(), k)); return *this; } inline auto& pop_kth_largest(const size_type k) const noexcept(NO_EXCEPT) { return this->erase(std::ranges::prev(this->end(), k + 1)); return *this; } auto next_element(const typename Set::key_type& key, const size_type _count = 0) const noexcept(NO_EXCEPT) { size_type count = std::abs(_count); auto itr = this->lower_bound(key); const auto begin = this->begin(), end = this->end(); if(itr == end) return this->end(); if(itr == begin) return this->begin(); while(count--) { if(_count < 0) if(itr-- == begin) return this->begin(); if(_count > 0) if(++itr == end) return this->end(); } return itr; } auto prev_element(const typename Set::key_type& key, const size_type _count = 0) const noexcept(NO_EXCEPT) { size_type count = std::abs(_count); auto itr = this->upper_bound(key); const auto begin = this->begin(), end = this->end(); if(itr == end) return this->end(); if(itr-- == begin) return this->begin(); while(count--) { if(_count < 0) if(itr-- == begin) return this->begin(); if(_count > 0) if(++itr == end) return this->end(); } return itr; } std::optional<typename Set::value_type> next(const typename Set::key_type& key, size_type count = 0) const noexcept(NO_EXCEPT) { if(this->empty()) return {}; auto itr = this->lower_bound(key); const auto end = this->end(); if(itr == end) return {}; while(count--) if(++itr == end) return {}; return { *itr }; } std::optional<typename Set::value_type> prev(const typename Set::key_type& key, size_type count = 0) const noexcept(NO_EXCEPT) { if(this->empty()) return {}; auto itr = this->upper_bound(key); const auto begin = this->begin(); if(itr-- == begin) return {}; while(count--) if(itr-- == begin) return {}; return { *itr }; } template<class Rhs> inline set_wrapper& operator|=(Rhs&& rhs) noexcept(NO_EXCEPT) { set_wrapper res; std::ranges::set_union(*this, std::forward<Rhs>(rhs), std::inserter(res, res.end())); this->swap(res); return *this; } template<class Rhs> inline set_wrapper& operator&=(Rhs&& rhs) noexcept(NO_EXCEPT) { set_wrapper res; std::ranges::set_intersection(*this, std::forward<Rhs>(rhs), std::inserter(res, res.end())); this->swap(res); return *this; } template<class Rhs> inline set_wrapper& operator^=(Rhs&& rhs) noexcept(NO_EXCEPT) { set_wrapper res; std::ranges::set_symmetric_difference(*this, std::forward<Rhs>(rhs), std::inserter(res, res.end())); this->swap(res); return *this; } template<class... Args> inline set_wrapper operator|(set_wrapper<Args...> rhs) noexcept(NO_EXCEPT) { return rhs |= *this; } template<class... Args> inline set_wrapper operator&(set_wrapper<Args...> rhs) noexcept(NO_EXCEPT) { return rhs &= *this; } template<class... Args> inline set_wrapper operator^(set_wrapper<Args...> rhs) noexcept(NO_EXCEPT) { return rhs ^= *this; } template<class... Args> inline auto operator<=>(const set_wrapper<Args...>& rhs) const noexcept(NO_EXCEPT) { const bool leq = this->size() <= rhs.size() && std::ranges::includes(rhs, *this); const bool geq = rhs.size() <= this->size() && std::ranges::includes(*this, rhs); if(leq) { if(geq) return std::partial_ordering::equivalent; return std::partial_ordering::less; } if(geq) return std::partial_ordering::greater; return std::partial_ordering::unordered; } }; } //namespace internal template<class... Args> using set = internal::set_wrapper<std::set<Args...>>; template<class... Args> using unordered_set = internal::set_wrapper<std::unordered_set<Args...>>; template<class... Args> using multiset = internal::set_wrapper<std::multiset<Args...>>; template<class... Args> using unordered_multiset = internal::set_wrapper<std::unordered_multiset<Args...>>; } // namespace uni #line 2 "adaptor/map.hpp" #include <map> #include <unordered_map> #line 7 "adaptor/map.hpp" #line 11 "adaptor/map.hpp" #line 2 "adaptor/gnu/hash_table.hpp" #line 5 "adaptor/gnu/hash_table.hpp" #include <stdexcept> #include <ext/pb_ds/assoc_container.hpp> #line 11 "adaptor/gnu/hash_table.hpp" namespace uni { namespace gnu { template<class Base> struct hash_table : Base { using key_type = typename Base::key_type; using value_type = typename Base::value_type; using mapped_type = typename Base::mapped_type; inline bool contains(const key_type& key) const noexcept(NO_EXCEPT) { return this->Base::find(key) != this->Base::end(); } template<class K, class T> inline decltype(auto) emplace(K&& key, T&& val) noexcept(NO_EXCEPT) { return this->Base::insert({ std::forward<K>(key), std::forward<T>(val) }); } mapped_type& at(const key_type& key) { auto itr = this->Base::find(key); if(itr == this->Base::end()) throw std::out_of_range("hash_table::at()"); return itr->second; }; const mapped_type& at(const key_type & key) const { auto itr = this->Base::find(key); if(itr == this->Base::end()) throw std::out_of_range("hash_table::at()"); return itr->second; }; }; template<class Key, class T, class Hash = void> struct cc_hash_table : hash_table<__gnu_pbds::cc_hash_table<Key, T, Hash>> { using hash_table<__gnu_pbds::cc_hash_table<Key, T, Hash>>::hash_table; }; template<class Key, class T> struct cc_hash_table<Key, T, void> : hash_table<__gnu_pbds::cc_hash_table<Key, T>> { using hash_table<__gnu_pbds::cc_hash_table<Key, T>>::hash_table; }; template<class Key, class T, class Hash = void> struct gp_hash_table : hash_table<__gnu_pbds::gp_hash_table<Key, T, Hash>> { using hash_table<__gnu_pbds::gp_hash_table<Key, T, Hash>>::hash_table; }; template<class Key, class T> struct gp_hash_table<Key, T, void> : hash_table<__gnu_pbds::gp_hash_table<Key, T>> { using hash_table<__gnu_pbds::gp_hash_table<Key, T>>::hash_table; }; } // namespace gnu } // namespace uni #line 14 "adaptor/map.hpp" namespace uni { namespace internal { template<class Map> using map_wrapper_base = set_wrapper<Map>; template<class Map> struct map_wrapper : map_wrapper_base<Map> { private: using base = map_wrapper_base<Map>; public: using base::base; using mapped_type = typename base::mapped_type; using key_type = typename base::key_type; protected: using default_func_noarg_type = std::function<mapped_type(void)>; using default_func_type = std::function<mapped_type(key_type)>; int _default_type = 0; mapped_type _default_val = mapped_type(); default_func_noarg_type _default_func_noarg; default_func_type _default_func; inline mapped_type _get_default(const key_type& key) const noexcept(NO_EXCEPT) { if(this->_default_type == 0) return this->_default_val; if(this->_default_type == 1) return this->_default_func_noarg(); if(this->_default_type == 2) return this->_default_func(key); else assert(false); } public: inline auto& set_default(const mapped_type& val) noexcept(NO_EXCEPT) { this->_default_val = val; this->_default_type = 0; return *this; } inline auto& set_default(const default_func_noarg_type func) noexcept(NO_EXCEPT) { this->_default_func_noarg = func; this->_default_type = 1; return *this; } inline auto& set_default(const default_func_type func) noexcept(NO_EXCEPT) { this->_default_func = func; this->_default_type = 2; return *this; } inline auto& operator[](const key_type& key) noexcept(NO_EXCEPT) { auto found = this->base::find(key); if(found == this->base::end()) return this->base::emplace(key, this->_get_default(key)).first->second; return found->second; } inline auto& operator()(const key_type& key) noexcept(NO_EXCEPT) { return this->base::operator[](key); } inline std::optional<mapped_type> get(const key_type& key) const noexcept(NO_EXCEPT) { const auto found = this->base::find(key); if(found == this->base::end()) return {}; return found->second; } }; } // namespace internal template<class... Args> using map = internal::map_wrapper<std::map<Args...>>; template<class... Args> using unordered_map = internal::map_wrapper<std::unordered_map<Args...>>; template<class... Args> using multimap = internal::map_wrapper<std::multimap<Args...>>; template<class... Args> using unordered_multimap = internal::map_wrapper<std::unordered_multimap<Args...>>; template<class... Args> using cc_hash_table = internal::map_wrapper<gnu::cc_hash_table<Args...>>; template<class... Args> using gp_hash_table = internal::map_wrapper<gnu::gp_hash_table<Args...>>; } // namespace uni #line 11 "numeric/fast_prime.hpp" #line 2 "numeric/internal/primality_test.hpp" #line 7 "numeric/internal/primality_test.hpp" #line 10 "numeric/internal/primality_test.hpp" #line 2 "numeric/modular/modint_interface.hpp" #line 6 "numeric/modular/modint_interface.hpp" #line 9 "numeric/modular/modint_interface.hpp" #line 11 "numeric/modular/modint_interface.hpp" #line 2 "numeric/modular/builtin_reduction.hpp" #line 5 "numeric/modular/builtin_reduction.hpp" #line 8 "numeric/modular/builtin_reduction.hpp" #line 10 "numeric/modular/builtin_reduction.hpp" #line 12 "numeric/modular/builtin_reduction.hpp" namespace uni { namespace internal { template<std::unsigned_integral Value, std::unsigned_integral Large> requires has_double_digits_of<Large, Value> struct builtin_reduction { using value_type = Value; using large_type = Large; private: value_type _mod; public: static constexpr int digits = std::numeric_limits<value_type>::digits; static constexpr value_type max() noexcept { return std::numeric_limits<value_type>::max(); } inline constexpr value_type mod() const noexcept(NO_EXCEPT) { return this->_mod; } constexpr builtin_reduction() noexcept = default; constexpr builtin_reduction(const value_type mod) noexcept(NO_EXCEPT) : _mod(mod) { assert(0 < mod && mod < builtin_reduction::max()); } inline constexpr value_type reduce(const large_type v) const noexcept(NO_EXCEPT) { return v % this->_mod; } inline constexpr value_type add(value_type x, const value_type y) const noexcept(NO_EXCEPT) { if(x >= this->_mod - y) x -= this->_mod; x += y; return x; } inline constexpr value_type subtract(value_type x, const value_type y) const noexcept(NO_EXCEPT) { if(x < y) x += this->_mod; x -= y; return x; } inline constexpr value_type multiply(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return this->reduce(static_cast<large_type>(x) * static_cast<large_type>(y)); } template<std::integral K> inline constexpr value_type pow(const value_type v, const K p) const noexcept(NO_EXCEPT) { if constexpr(std::signed_integral<K>) assert(p >= 0); if(this->_mod == 0) return 0; return uni::pow(v, p, [this](const value_type x, const value_type y) { return this->multiply(x, y); }); } inline constexpr auto compare(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return x <=> y; } constexpr value_type convert_raw(const value_type v) const noexcept(NO_EXCEPT) { return v; } template<std::integral T> constexpr value_type convert(T v) const noexcept(NO_EXCEPT) { using common_type = std::common_type_t<T, value_type>; const common_type mod = static_cast<common_type>(this->_mod); if(std::is_constant_evaluated()) { v %= mod; if constexpr(std::signed_integral<T>) { if(v < 0) v += mod; } } else { if(v > 0 && static_cast<common_type>(v) >= mod) { v %= mod; } if constexpr(std::signed_integral<T>) { if(v < 0) { if(static_cast<common_type>(-v) <= mod) v += mod; else { v %= mod; if(v != 0) v += mod; } } } } return static_cast<value_type>(v); } constexpr value_type revert(const value_type v) const noexcept(NO_EXCEPT) { return this->_mod == 1 ? 0 : v; } }; } // namespace internal using builtin_reduction_32bit = internal::builtin_reduction<u32, u64>; using builtin_reduction_64bit = internal::builtin_reduction<u64, u128>; } // namespace uni #line 2 "numeric/modular/binary_reduction.hpp" #line 7 "numeric/modular/binary_reduction.hpp" #line 10 "numeric/modular/binary_reduction.hpp" #line 13 "numeric/modular/binary_reduction.hpp" #line 2 "numeric/bit.hpp" #include <immintrin.h> #line 13 "numeric/bit.hpp" #line 16 "numeric/bit.hpp" #line 18 "numeric/bit.hpp" namespace uni { template<std::unsigned_integral T> constexpr T multiply_high(const T x, const T y) noexcept(NO_EXCEPT) { constexpr int digits = std::numeric_limits<T>::digits; if constexpr(digits <= 16) { return static_cast<T>((static_cast<u32>(x) * static_cast<u32>(y)) >> digits); } else if constexpr(digits <= 32) { return static_cast<T>((static_cast<u64>(x) * static_cast<u64>(y)) >> digits); } else if constexpr(digits <= 64) { return static_cast<T>((static_cast<u128>(x) * static_cast<u128>(y)) >> digits); } else { constexpr int h_digits = digits / 2; constexpr T mask = (T{ 1 } << h_digits) - 1; const T xh = x >> h_digits, yh = y >> h_digits; const T xl = x & mask, yl = y & mask; const T ph = xh * yh, pl = xl * yl; return (((pl >> h_digits) + (xh + xl) * (yh + yl) - (ph + pl)) >> h_digits) + ph; } } template<std::unsigned_integral T> inline constexpr int highest_bit_pos(const T v) noexcept(NO_EXCEPT) { return (int)std::bit_width(v) - 1; // cast to int for GCC12 } template<std::unsigned_integral T> inline constexpr int lowest_bit_pos(const T v) noexcept(NO_EXCEPT) { if(v == 0) return -1; return std::countr_zero(v); } template<std::unsigned_integral T, std::integral I = int> __attribute__((target("bmi2"))) inline constexpr T clear_higher_bits(const T v, const I p) { if constexpr(std::signed_integral<I>) assert(0 <= p); constexpr int DIGITS = std::numeric_limits<T>::digits; assert(p <= DIGITS); if constexpr(DIGITS <= 32) return _bzhi_u32(v, static_cast<u32>(p)); if constexpr(DIGITS <= 64) return _bzhi_u64(v, static_cast<u64>(p)); else { static_assert(DIGITS <= 128); constexpr std::uint64_t MAX64 = std::numeric_limits<std::uint64_t>::max(); const std::uint64_t high = v >> 64; const std::uint64_t low = v & MAX64; if(p < 64) return _bzhi_u64(low, p); return low | (T{_bzhi_u64(high, p - 64)} << 64); } } template<std::unsigned_integral T, std::integral I = int> constexpr T shiftl(const T, const I = 1); template<std::unsigned_integral T, std::integral I = int> constexpr T shiftr(const T, const I = 1); template<std::unsigned_integral T, std::integral I> constexpr T shiftl(const T x, const I n) { constexpr int DIGITS = std::numeric_limits<T>::digits; if constexpr(std::signed_integral<I>) { if(n < 0) return shiftr(x, -n); } if(n >= DIGITS) return 0; return x << n; } template<std::unsigned_integral T, std::integral I> constexpr T shiftr(const T x, const I n) { constexpr int DIGITS = std::numeric_limits<T>::digits; if constexpr(std::signed_integral<I>) { if(n < 0) return shiftl(x, -n); } if(n >= DIGITS) return 0; return x >> n; } template<std::unsigned_integral T, std::integral I = int> inline constexpr bool bit(const T x, const I p) { if constexpr(std::signed_integral<I>) assert(0 <= p); assert(p < std::numeric_limits<T>::digits); return shiftr(x, p) & T{1}; } template<std::unsigned_integral T, std::integral I = int> inline constexpr auto reset_bit(const T x, const I p) { if constexpr(std::signed_integral<I>) assert(0 <= p); assert(p < std::numeric_limits<T>::digits); return x & ~(T{1} << p); } template<std::unsigned_integral T, std::integral I = int> inline constexpr auto set_bit(const T x, const I p, const bool bit = true) { if constexpr(std::signed_integral<I>) assert(0 <= p); assert(p < std::numeric_limits<T>::digits); if(!bit) return reset_bit(x, p); return x | (T{1} << p); } template<std::unsigned_integral T, std::integral I = int> inline constexpr T lower_bits(const T x, const I digits) { if constexpr(std::signed_integral<I>) assert(0 <= digits); assert(digits <= std::numeric_limits<T>::digits); return x & (uni::shiftl(x, digits) - 1); } // Thanks to: https://noshi91.github.io/Library/other/select64.cpp constexpr int select64(const u64 x0, u32 k) { const u64 x1 = (x0 & UINT64_C(0x5555555555555555)) + (x0 >> 1 & UINT64_C(0x5555555555555555)); const u64 x2 = (x1 & UINT64_C(0x3333333333333333)) + (x1 >> 2 & UINT64_C(0x3333333333333333)); const u64 x3 = (x2 & UINT64_C(0x0F0F0F0F0F0F0F0F)) + (x2 >> 4 & UINT64_C(0x0F0F0F0F0F0F0F0F)); const u64 x4 = (x3 & UINT64_C(0x00FF00FF00FF00FF)) + (x3 >> 8 & UINT64_C(0x00FF00FF00FF00FF)); const u64 x5 = (x4 & UINT64_C(0x0000FFFF0000FFFF)) + (x4 >> 16 & UINT64_C(0x0000FFFF0000FFFF)); int res = 0; u32 t; t = x5 & 0xFFFFFFFF; if(t <= k) k -= t, res += 32; t = x4 >> res & 0xFFFF; if(t <= k) k -= t, res += 16; t = x3 >> res & 0xFF; if(t <= k) k -= t, res += 8; t = x2 >> res & 0xF; if(t <= k) k -= t, res += 4; t = x1 >> res & 0x3; if(t <= k) k -= t, res += 2; t = x0 >> res & 0x1; if(t <= k) k -= t, res += 1; return res; } namespace internal { template<std::unsigned_integral T> constexpr T binary_gcd(T a, T b) noexcept(NO_EXCEPT) { if(!a || !b) return a | b; T t, s = std::countr_zero(a | b); a >>= std::countr_zero(a); do { b >>= std::countr_zero(b); if(a > b) t = a, a = b, b = t; b -= a; } while(b); return a << s; } template<std::signed_integral T> inline constexpr T binary_gcd(const T a, const T b) noexcept(NO_EXCEPT) { return binary_gcd(a < 0 ? -a : a, b < 0 ? -b : b); } } // namespace internal template<std::integral T0, std::integral T1> inline constexpr auto binary_gcd(T0 v0, T1 v1) noexcept(NO_EXCEPT) { using common_type = std::common_type_t<T0, T1>; return internal::binary_gcd(static_cast<common_type>(v0), static_cast<common_type>(v1)); } template<std::unsigned_integral T, std::unsigned_integral S> inline constexpr bool is_subset_of(T target, S superset) noexcept(NO_EXCEPT) { return (target & ~superset) == 0; } template<std::unsigned_integral T, std::unsigned_integral S> inline constexpr bool is_superset_of(T target, S subset) noexcept(NO_EXCEPT) { return (~target & subset) == 0; } template<std::unsigned_integral S0, std::unsigned_integral S1> inline constexpr auto comapre_as_bitset(S0 s0, S1 s1) noexcept(NO_EXCEPT) { if(s0 == s1) return std::partial_ordering::equivalent; if(is_subset_of(s0, s1)) return std::partial_ordering::less; if(is_superset_of(s0, s1)) return std::partial_ordering::greater; return std::partial_ordering::unordered; } } // namespace uni #line 16 "numeric/modular/binary_reduction.hpp" namespace uni { namespace internal { template<std::unsigned_integral Value> struct binary_reduction { using value_type = Value; private: value_type _mask; public: static constexpr int digits = std::numeric_limits<value_type>::digits; static constexpr value_type max() noexcept { return std::numeric_limits<value_type>::max(); } inline constexpr value_type mod() const noexcept(NO_EXCEPT) { return this->_mask + 1; } constexpr binary_reduction() noexcept = default; constexpr explicit inline binary_reduction(const value_type mod) noexcept(NO_EXCEPT) : _mask(mod - 1) { assert(std::has_single_bit(mod)); } inline constexpr value_type reduce(const value_type v) const noexcept(NO_EXCEPT) { return v; } inline constexpr value_type add(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return x + y; } inline constexpr value_type subtract(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return x - y; } inline constexpr value_type multiply(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return x * y; } template<std::integral K> inline constexpr value_type pow(const value_type v, const K p) const noexcept(NO_EXCEPT) { if constexpr(std::signed_integral<K>) assert(p >= 0); if(this->_mask == 0) return 0; return uni::pow(v, p); } inline constexpr auto compare(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return this->revert(x) <=> this->revert(y); } constexpr value_type convert_raw(const value_type v) const noexcept(NO_EXCEPT) { return v; } template<std::integral T> constexpr value_type convert(T v) const noexcept(NO_EXCEPT) { return static_cast<value_type>(v); } constexpr value_type revert(const value_type v) const noexcept(NO_EXCEPT) { return v & this->_mask; } }; } // namespace internal using binary_reduction_32bit = internal::binary_reduction<u32>; using binary_reduction_64bit = internal::binary_reduction<u64>; using binary_reduction_128bit = internal::binary_reduction<u128>; } // namespace uni #line 2 "numeric/modular/barrett_reduction.hpp" #line 8 "numeric/modular/barrett_reduction.hpp" #line 11 "numeric/modular/barrett_reduction.hpp" #line 14 "numeric/modular/barrett_reduction.hpp" #line 2 "template/debug.hpp" #ifdef LOCAL_JUDGE #define DEBUGGER_ENABLED #define DEBUGGER_COLORED_OUTPUT 1 #endif #line 2 "debugger/debug.hpp" #line 9 "debugger/debug.hpp" #include <array> #line 13 "debugger/debug.hpp" #include <bitset> #include <deque> #include <queue> #include <stack> #line 22 "debugger/debug.hpp" #include <iomanip> #line 26 "debugger/debug.hpp" #line 2 "numeric/int128.hpp" #include <cctype> #line 9 "numeric/int128.hpp" #line 12 "numeric/int128.hpp" #line 14 "numeric/int128.hpp" namespace std { template<class C, class S> auto& operator>>(std::basic_istream<C, S>& in, uni::i128& v) noexcept(NO_EXCEPT) { std::string str; in >> str; v = 0; bool negative = (str[0] == '-'); REP(d, std::ranges::next(str.begin(), negative), str.end()) { assert(std::isdigit(*d)); v = v * 10 + *d - '0'; } if(negative) v *= -1; return in; } template<class C, class S> auto& operator>>(std::basic_istream<C, S>& in, uni::u128& v) noexcept(NO_EXCEPT) { std::string str; in >> str; v = 0U; assert(str[0] != '-'); REP(d, str.begin(), str.end()) { assert(std::isdigit(*d)); v = v * 10U + *d - '0'; } return in; } template<class C, class S> auto& operator<<(std::basic_ostream<C, S>& out, uni::i128 v) noexcept(NO_EXCEPT) { if(v == 0) return out << 0; if(v < 0) out << '-', v *= -1; std::string str; while(v > 0) str += static_cast<char>(v%10) + '0', v /= 10; std::reverse(str.begin(), str.end()); return out << str; } template<class C, class S> auto& operator<<(std::basic_ostream<C, S>& out, uni::u128 v) noexcept(NO_EXCEPT) { if(v == 0) return out << 0U; std::string str; while(v > 0) str += static_cast<char>(v%10U) + '0', v /= 10U; std::reverse(str.begin(), str.end()); return out << str; } } #line 29 "debugger/debug.hpp" #line 2 "internal/resolving_rank.hpp" namespace uni { namespace internal { template<int P> struct resolving_rank : resolving_rank<P-1> {}; template<> struct resolving_rank<0> {}; } // namespace internal } // namespace uni #line 34 "debugger/debug.hpp" #include <typeinfo> #include <cxxabi.h> namespace debugger { template<class T> auto _debug (T&& val) -> decltype(val._debug()) { return val._debug(); } std::ostream *cdebug = &std::clog; #ifdef DEBUGGER_COLORED_OUTPUT constexpr std::string COLOR_LINE = "\033[3;35m"; constexpr std::string COLOR_IDENTIFIER = "\033[32m"; constexpr std::string COLOR_INIT = "\033[m"; constexpr std::string COLOR_STRING = "\033[33m"; constexpr std::string COLOR_TYPE = "\033[34m"; constexpr std::string COLOR_NUMERIC = "\033[36m"; constexpr std::string COLOR_LITERAL_OPERATOR = "\033[31m"; #else constexpr std::string COLOR_LINE = ""; constexpr std::string COLOR_IDENTIFIER = ""; constexpr std::string COLOR_INIT = ""; constexpr std::string COLOR_STRING = ""; constexpr std::string COLOR_TYPE = ""; constexpr std::string COLOR_NUMERIC = ""; constexpr std::string COLOR_LITERAL_OPERATOR = ""; #endif using Brackets = std::pair<std::string, std::string>; template<class T> std::string dump(T&&); template<class T> const std::string get_type_name(T&& val) { const char* const name = typeid(std::forward<T>(val)).name(); int status = -4; char* const demangled_name = abi::__cxa_demangle(name, NULL, NULL, &status); std::string res{name}; if (status == 0) { res = std::string(demangled_name); free(demangled_name); } return COLOR_TYPE + res + COLOR_INIT; } struct debug_t : std::string { using std::string::string; debug_t(const std::string& str) { this->assign(str); } }; template<size_t N, class T> void dump_tuple_impl([[maybe_unused]] T&& val, std::stringstream &res) { if constexpr(N < std::tuple_size_v<std::remove_cvref_t<T>>) { res << dump(std::get<N>(val)); if constexpr(N < std::tuple_size_v<std::remove_cvref_t<T>> - 1) res << ", "; dump_tuple_impl<N + 1>(std::forward<T>(val), res); } } template<std::ranges::input_range R> std::string dump_range_impl(R&& range, const Brackets& brcs = { "[", "]" }, const std::string& spl = ", ") { std::stringstream res; res << brcs.first << " "; auto itr = std::ranges::begin(range); auto end = std::ranges::end(std::forward<R>(range)); while(itr != end) { if(std::ranges::next(itr) == end) res << dump(*itr) << " "; else res << dump(*itr) << spl; ++itr; } res << brcs.second ; return res.str(); } std::string dump_debug_t(debug_t info) { return info; } struct dump_primitive_like { std::string operator()(std::nullptr_t) const { return COLOR_INIT; } template<uni::internal::pointer T> std::string operator()(const T ptr) const { return dump(*ptr); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::basic_string> std::string operator()(T&& val) const { std::stringstream res; res << COLOR_STRING << "`" << val << "`" << COLOR_INIT; return res.str(); } std::string operator()(const char val) const { std::stringstream res; res << COLOR_STRING << "\'" << val << "\'" << COLOR_INIT; return res.str(); } std::string operator()(const char val[]) const { std::stringstream res; res << COLOR_STRING << "\"" << val << "\"" << COLOR_INIT; return res.str(); } std::string operator()(const unsigned char val) const { std::stringstream res; res << COLOR_NUMERIC << static_cast<int>(val) << COLOR_INIT; return res.str(); } std::string operator()(const bool val) const { std::stringstream res; res << COLOR_NUMERIC << (val ? "true" : "false" ) << COLOR_INIT; return res.str(); } template<uni::internal::arithmetic T> std::string operator()(const T val) const { std::stringstream res; res << std::setprecision(std::numeric_limits<T>::digits10) << val; auto str = res.str(); std::string dst = ""; while(str.length() > 3) { dst = ',' + str.substr(str.length() - 3, 3) + dst; str = str.substr(0, str.length() - 3); } return COLOR_NUMERIC + str + dst + COLOR_LITERAL_OPERATOR + uni::internal::literal_operator_v<T> + COLOR_INIT; }; template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::optional> std::string operator()(T&& val) const { if(val.has_value()) return dump(*val); return COLOR_TYPE + "invalid" + COLOR_INIT; } }; struct dump_bitset { template<std::size_t N> std::string operator()(const std::bitset<N>& val) const { std::stringstream res; res << COLOR_NUMERIC << val.to_string() << COLOR_INIT; return res.str(); } }; struct dump_has_val { template<class T> requires requires (T val) { val.val(); } std::string operator()(T&& val) const { return dump(val.val()); } }; struct dump_iterator { template<std::input_or_output_iterator I> std::string operator()(I&& itr) const { return COLOR_TYPE + "<iterator> " + COLOR_INIT+ dump(*itr); } }; struct dump_wrapper { template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::map> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::multimap> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::unordered_map> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::unordered_multimap> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::set> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::multiset> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::unordered_set> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::unordered_multiset> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("{", "}")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::valarray> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("[", "]")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::vector> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("[", "]")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::deque> std::string operator()(T&& val) const { return dump_range_impl(val, Brackets("[", "]")); } template<uni::internal::derived_from_template<std::queue> T> std::string operator()(T val) const { std::vector<typename T::value_type> vec; while(!val.empty()) vec.emplace_back(val.front()), val.pop(); return dump_range_impl(vec, Brackets("<", ">")); } template<uni::internal::derived_from_template<std::stack> T> std::string operator()(T val) const { std::vector<typename T::value_type> vec; while(!val.empty()) vec.emplace_back(val.top()), val.pop(); std::ranges::reverse(vec); return dump_range_impl(vec, Brackets("<", ">")); } template<uni::internal::derived_from_template<std::priority_queue> T> std::string operator()(T val) const { std::vector<typename T::value_type> vec; while(!val.empty()) vec.emplace_back(val.top()), val.pop(); return dump_range_impl(vec, Brackets("<", ">")); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::pair> std::string operator()(T&& val) const { std::stringstream res; res << "( " << dump(val.first) << ", " << dump(val.second) << " )"; return res.str(); } template<class T> requires uni::internal::derived_from_template<std::remove_cvref_t<T>, std::tuple> std::string operator()(T&& val) const { std::stringstream res; res << "( "; dump_tuple_impl<0>(val, res); res << " )"; return res.str(); } }; struct dump_range { template<std::ranges::input_range T> std::string operator()(T&& val) const { return dump_range_impl(val); } }; struct dump_loggable { template<uni::internal::loggable T> std::string operator()(T&& val) const { auto res = _debug(val); if constexpr(std::same_as<decltype(res), debug_t>) { return res; } else { return dump(res); } } }; template<class T> std::string dump(T&& val) { if constexpr(std::same_as<std::remove_cvref_t<T>, debug_t>) { // return "debug_t"; return dump_debug_t(std::forward<T>(val)); } if constexpr(std::invocable<dump_primitive_like, T>) { // return "primitive"; return dump_primitive_like{}(std::forward<T>(val)); } if constexpr(std::invocable<dump_loggable, T>) { // return "loggable"; return dump_loggable{}(std::forward<T>(val)); } if constexpr(std::invocable<dump_has_val, T>) { // return "has val"; return dump_has_val{}(std::forward<T>(val)); } if constexpr(std::invocable<dump_bitset, T>) { // return "bitset"; return dump_bitset{}(std::forward<T>(val)); } if constexpr(std::invocable<dump_iterator, T>) { // return "iterator"; return dump_iterator{}(std::forward<T>(val)); } if constexpr(std::invocable<dump_wrapper, T>) { // return "wrapper"; return dump_wrapper{}(std::forward<T>(val)); } if constexpr(std::invocable<dump_range, T>) {; // return "range"; return dump_range{}(std::forward<T>(val)); } return "== dump error =="; } template<class T> void debug(T&& val, const std::string& endl) { *cdebug << dump(val) << endl << std::flush; } constexpr std::string_view WHITESPACES = " \n\r\t\f\v"; std::string ltrim(const std::string &s) { size_t start = s.find_first_not_of(WHITESPACES); return (start == std::string::npos) ? "" : s.substr(start); } std::string rtrim(const std::string &s) { size_t end = s.find_last_not_of(WHITESPACES); return (end == std::string::npos) ? "" : s.substr(0, end + 1); } std::string trim(const std::string &s) { return rtrim(ltrim(s)); } std::vector<std::string> split(const std::string& str) { static constexpr char SEPARATOR = ','; static constexpr char ESCAPE = '\\'; static constexpr std::string_view QUOTATIONS = "\"\'"; static constexpr std::string_view PARENTHESES = "()[]{}<>"; static constexpr auto PARENTHESES_KINDS = std::ranges::size(PARENTHESES); static_assert(PARENTHESES_KINDS % 2 == 0); std::vector<std::string> res = { "" }; bool quoted = false; std::array<int,(PARENTHESES_KINDS / 2)> enclosed = { 0 }; for(auto itr = std::ranges::begin(str); itr != std::ranges::end(str); ++itr) { if(std::ranges::find(QUOTATIONS, *itr) != std::ranges::end(QUOTATIONS)) { if(itr == std::ranges::begin(str) or *std::ranges::prev(itr) != ESCAPE) { quoted ^= true; } } if(const auto found = std::ranges::find(PARENTHESES, *itr); found != std::ranges::end(PARENTHESES)) { if(not quoted) { auto& target = enclosed[std::ranges::distance(std::begin(PARENTHESES), found) / 2]; target = std::max(0, target - static_cast<int>((std::ranges::distance(std::begin(PARENTHESES), found) % 2) * 2) + 1); } } if( not quoted and static_cast<std::size_t>(std::ranges::count(enclosed, 0)) == std::ranges::size(enclosed) and *itr == SEPARATOR ) { res.push_back(""); } else { res.back() += *itr; } } for(auto&& v : res) v = trim(v); return res; } template<class Arg> void raw(std::nullptr_t, Arg&& arg) { *cdebug << std::forward<Arg>(arg) << std::flush; } template<class Arg> void raw(Arg&& arg) { *cdebug << dump(std::forward<Arg>(arg)) << std::flush; } void debug(const std::vector<std::string>, const size_t, const int, const std::string) { debug(nullptr, COLOR_INIT + "\n"); } std::map<std::pair<std::string, int>, int> count; template<class Head, class... Tail> void debug( const std::vector<std::string> args, const size_t idx, const int line, const std::string path, Head&& H, Tail&&... T ) { if(idx == 0) { std::string file = path.substr(path.find_last_of("/") + 1); debug(nullptr, COLOR_LINE + file + " #" + std::to_string(line) + " (" + std::to_string(count[{ file, line }]++) + ")" + COLOR_INIT); } debug(nullptr, "\n - "); const std::string content = dump(H); const std::string type_name = get_type_name(std::forward<Head>(H)); debug(nullptr, COLOR_IDENTIFIER + args[idx] + COLOR_INIT + " : "); debug(nullptr, content); if(type_name.size() + content.size() >= 300) debug(nullptr, "\n "); debug(nullptr, " " + type_name); debug(args, idx + 1, 0, path, std::forward<Tail>(T)...); } } // namespace debugger #line 13 "template/debug.hpp" #ifdef DEBUGGER_ENABLED #define debug(...) debugger::debug(debugger::split(#__VA_ARGS__), 0, __LINE__, __FILE__, __VA_ARGS__) #define debug_(...) do { const std::string file = __FILE__; debugger::raw(nullptr, debugger::COLOR_LINE + file.substr(file.find_last_of("/") + 1) + " #" + std::to_string(__LINE__) + debugger::COLOR_INIT + " "); debugger::raw(__VA_ARGS__); debugger::raw(nullptr, debugger::COLOR_INIT + "\n"); } while(0); #define DEBUG if constexpr(true) #else #define debug(...) ({ ; }) #define debug_(...) ({ ; }) #define DEBUG if constexpr(false) #endif #line 18 "numeric/modular/barrett_reduction.hpp" namespace uni { namespace internal { template<std::unsigned_integral Value, std::unsigned_integral Large> requires has_double_digits_of<Large, Value> struct barrett_reduction { using value_type = Value; using large_type = Large; private: large_type _mod = 0, _mi; inline constexpr std::pair<large_type,value_type> _reduce(const large_type v) const noexcept(NO_EXCEPT) { large_type x = multiply_high(v, this->_mi); return { x, static_cast<value_type>(v - x * this->_mod) }; } public: static constexpr int digits = std::numeric_limits<value_type>::digits - 1; static constexpr value_type max() noexcept { return (value_type{ 1 } << barrett_reduction::digits) - 1; } inline constexpr value_type mod() const noexcept(NO_EXCEPT) { return this->_mod; } constexpr barrett_reduction() noexcept = default; constexpr explicit inline barrett_reduction(const value_type mod) : _mod(mod), _mi(std::numeric_limits<large_type>::max() / mod + 1) { assert(0 < mod && mod <= barrett_reduction::max()); } inline constexpr large_type quotient(const large_type v) const noexcept(NO_EXCEPT) { const auto [ x, r ] = this->_reduce(v); return static_cast<large_type>(this->_mod <= r ? x - 1 : x); } inline constexpr value_type reduce(const large_type v) const noexcept(NO_EXCEPT) { const auto [ x, r ] = this->_reduce(v); return static_cast<value_type>(this->_mod <= r ? r + this->_mod : r); } inline constexpr std::pair<large_type,value_type> divide(const large_type v) const noexcept(NO_EXCEPT) { const auto [ x, r ] = this->_reduce(v); if(this->_mod <= r) return { static_cast<large_type>(x - 1), static_cast<value_type>(r + this->_mod) }; return { static_cast<large_type>(x), static_cast<value_type>(r) }; } inline constexpr value_type add(value_type x, const value_type y) const noexcept(NO_EXCEPT) { x += y; if(x >= this->_mod) x -= this->_mod; return x; } inline constexpr value_type subtract(value_type x, const value_type y) const noexcept(NO_EXCEPT) { if(x < y) x += this->_mod; x -= y; return x; } inline constexpr value_type multiply(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return this->reduce(static_cast<large_type>(x) * static_cast<large_type>(y)); } template<std::integral K> inline constexpr value_type pow(const large_type v, const K p) const noexcept(NO_EXCEPT) { if constexpr(std::signed_integral<K>) assert(p >= 0); if(this->_mod == 1) return 0; return uni::pow( this->reduce(v), p, [&](const value_type x, const value_type y) noexcept(NO_EXCEPT) { return this->multiply(x, y); } ); } inline constexpr auto compare(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return x <=> y; } constexpr value_type convert_raw(const value_type v) const noexcept(NO_EXCEPT) { return v; } template<std::integral T> constexpr value_type convert(T v) const noexcept(NO_EXCEPT) { using common_type = std::common_type_t<T, value_type>; const common_type mod = static_cast<common_type>(this->_mod); if(v > 0 && static_cast<common_type>(v) >= mod) { if(static_cast<common_type>(v) <= barrett_reduction::max()) v = this->reduce(v); else v %= mod; } if constexpr(std::signed_integral<T>) { if(v < 0) { if(static_cast<common_type>(-v) <= mod) v += mod; else if(static_cast<common_type>(-v) <= barrett_reduction::max()) { v = mod - this->reduce(static_cast<value_type>(-v - 1)) - 1; } else { v %= mod; if(v != 0) v += mod; } } } return static_cast<value_type>(v); } constexpr value_type revert(const value_type v) const noexcept(NO_EXCEPT) { return this->reduce(v); } }; } // namespace internal using barrett_reduction_32bit = internal::barrett_reduction<u32, u64>; using barrett_reduction_64bit = internal::barrett_reduction<u64, u128>; } // namespace uni #line 2 "numeric/modular/montgomery_reduction.hpp" #line 7 "numeric/modular/montgomery_reduction.hpp" #line 10 "numeric/modular/montgomery_reduction.hpp" #line 16 "numeric/modular/montgomery_reduction.hpp" namespace uni { namespace internal { template<std::unsigned_integral Value, std::unsigned_integral Large> requires has_double_digits_of<Large, Value> struct montgomery_reduction { using value_type = Value; using large_type = Large; private: value_type _mod = 0, _r2, _mp; constexpr value_type _inv() const noexcept(NO_EXCEPT) { value_type res = this->_mod; while(this->_mod * res != 1) res *= value_type{ 2 } - this->_mod * res; return res; } public: static constexpr int digits = std::numeric_limits<value_type>::digits - 2; static constexpr value_type max() noexcept { return (value_type{ 1 } << montgomery_reduction::digits) - 1; } inline constexpr value_type mod() const noexcept(NO_EXCEPT) { return this->_mod; } value_type zero = 0; value_type one; constexpr montgomery_reduction() noexcept = default; constexpr montgomery_reduction(const value_type mod) noexcept(NO_EXCEPT) : _mod(mod), _r2(static_cast<value_type>(-static_cast<large_type>(mod) % mod)), _mp(-this->_inv()), one(this->reduce(this->_r2)) { assert((mod & 1) == 1); assert(mod <= montgomery_reduction::max()); } constexpr value_type reduce(const large_type v) const noexcept(NO_EXCEPT) { return static_cast<value_type>( ( v + static_cast<large_type>(static_cast<value_type>(v) * this->_mp) * this->_mod ) >> std::numeric_limits<value_type>::digits ); } inline constexpr value_type add(value_type x, const value_type y) const noexcept(NO_EXCEPT) { x += y; if(x >= (this->_mod << 1)) x -= (this->_mod << 1); return x; } inline constexpr value_type subtract(value_type x, const value_type y) const noexcept(NO_EXCEPT) { if(x < y) x += (this->_mod << 1); x -= y; return x; } inline constexpr value_type multiply(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return this->reduce(static_cast<large_type>(x) * static_cast<large_type>(y)); } template<std::integral K> inline constexpr value_type pow(const large_type v, const K p) const noexcept(NO_EXCEPT) { if constexpr(std::signed_integral<K>) assert(p >= 0); if(this->_mod == 1) return 0; return uni::pow( v, p, [&](const value_type x, const value_type y) noexcept(NO_EXCEPT) { return this->multiply(x, y); }, static_cast<large_type>(this->one) ); } inline constexpr value_type normalize(const value_type v) const noexcept(NO_EXCEPT) { assert(0 <= v && v < (this->_mod << 1)); if(v < this->_mod) return v; return v - this->_mod; } inline constexpr auto compare(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return this->normalize(x) <=> this->normalize(y); } inline constexpr value_type convert_raw(const value_type v) const noexcept(NO_EXCEPT) { if(v == 1) return this->one; return this->multiply(v, this->_r2); } template<std::integral T> constexpr value_type convert(T v) const noexcept(NO_EXCEPT) { if(v == 1) return this->one; using common_type = std::common_type_t<T, value_type>; const common_type mod2 = static_cast<common_type>(this->_mod << 1); if(v > 0 && static_cast<common_type>(v) >= mod2) { v %= mod2; } if constexpr(std::is_signed_v<T>) { if(v < 0 && static_cast<common_type>(-v) >= mod2) { v %= mod2; if(v != 0) v += mod2; } } return this->multiply(v, this->_r2); } constexpr value_type revert(const value_type v) const noexcept(NO_EXCEPT) { return this->normalize(this->reduce(v)); } }; // Thanks to: https://www.mathenachia.blog/even-mod-montgomery-impl/ template<std::unsigned_integral Value, std::unsigned_integral Large> requires has_double_digits_of<Large, Value> struct arbitrary_montgomery_reduction { using value_type = Value; using large_type = Large; private: using context = arbitrary_montgomery_reduction; static constexpr int width = std::numeric_limits<value_type>::digits; value_type _mod = 0; int _tz; value_type _m0; large_type _m0i, _mask; value_type _r2; constexpr large_type _inv() const noexcept(NO_EXCEPT) { large_type res = this->_m0; while(((this->_m0 * res) & this->_mask) != 1) res *= large_type{ 2 } - this->_m0 * res; return res & this->_mask; } constexpr value_type _m0ip() const noexcept(NO_EXCEPT) { if(this->_tz == 0) return 0; value_type res = this->_m0; const value_type mask = (value_type{ 1 } << this->_tz) - 1; while(((this->_m0 * res) & mask) != 1) res *= value_type{ 2 } - this->_m0 * res; return res & mask; } public: static constexpr int digits = std::numeric_limits<value_type>::digits - 2; static constexpr value_type max() noexcept { return (value_type{ 1 } << context::digits) - 1; } inline constexpr value_type mod() const noexcept(NO_EXCEPT) { return this->_mod; } value_type one; constexpr arbitrary_montgomery_reduction() noexcept = default; constexpr arbitrary_montgomery_reduction(value_type m) noexcept(NO_EXCEPT) { assert(0 < m); if(this->_mod == m) return; this->_mod = m; this->_tz = std::countr_zero(m); this->_m0 = m >> this->_tz; assert(this->_mod < context::max()); this->_mask = (large_type{ 1 } << (context::width + this->_tz)) - 1; this->_m0i = this->_inv(); { const value_type x = (std::numeric_limits<large_type>::max() % this->_m0) + 1; const value_type mask = (value_type{ 1 } << this->_tz) - 1; this->_r2 = (x + ((((large_type{ 1 } - x) * this->_m0ip()) & mask) * this->_m0)); } this->one = this->reduce(this->_r2); } constexpr value_type reduce(const large_type v) const noexcept(NO_EXCEPT) { const value_type res = static_cast<value_type>( ( v + this->_m0 * ((((v << std::numeric_limits<value_type>::digits) - v) * this->_m0i) & this->_mask) ) >> std::numeric_limits<value_type>::digits ); return res; } inline constexpr value_type add(value_type x, const value_type y) const noexcept(NO_EXCEPT) { x += y; if(x >= (this->_mod << 1)) x -= (this->_mod << 1); return x; } inline constexpr value_type subtract(value_type x, const value_type y) const noexcept(NO_EXCEPT) { if(x < y) x += (this->_mod << 1); x -= y; return x; } inline constexpr value_type multiply(const value_type x, const value_type y) const noexcept(NO_EXCEPT) { return this->reduce(static_cast<large_type>(x) * static_cast<large_type>(y)); } template<std::integral K> inline constexpr value_type pow(const large_type v, K p) const noexcept(NO_EXCEPT) { if constexpr(std::signed_integral<K>) assert(p >= 0); if(this->_mod == 1) return 0; return uni::pow( v, p, [&](const value_type x, const value_type y) noexcept(NO_EXCEPT) { return this->multiply(x, y); }, static_cast<large_type>(this->one) ); } inline constexpr value_type normalize(const value_type v) const noexcept(NO_EXCEPT) { assert(0 <= v && v < (this->_mod << 1)); if(v < this->_mod) return v; return v - this->_mod; } inline constexpr auto compare(const large_type x, const large_type y) const noexcept(NO_EXCEPT) { return this->normalize(x) <=> this->normalize(y); } inline constexpr value_type convert_raw(const value_type v) const noexcept(NO_EXCEPT) { if(v == 1) return this->one; return this->multiply(v, this->_r2); } template<std::integral T> constexpr value_type convert(T v) const noexcept(NO_EXCEPT) { if(v == 1) return this->one; using common_type = std::common_type_t<T, value_type>; const common_type mod2 = static_cast<common_type>(this->_mod << 1); if(v > 0 && static_cast<common_type>(v) >= mod2) { v %= mod2; } if constexpr(std::signed_integral<T>) { if(v < 0) { if(static_cast<common_type>(-v) >= mod2) v %= mod2; if(v < 0) v += mod2; } } return this->multiply(v, this->_r2); } constexpr value_type revert(const value_type v) const noexcept(NO_EXCEPT) { return this->normalize(this->reduce(v)); } }; } // namespace internal using montgomery_reduction_32bit = internal::montgomery_reduction<u32, u64>; using montgomery_reduction_64bit = internal::montgomery_reduction<u64, u128>; using arbitrary_montgomery_reduction_32bit = internal::arbitrary_montgomery_reduction<u32, u64>; using arbitrary_montgomery_reduction_64bit = internal::arbitrary_montgomery_reduction<u64, u128>; } // namespace uni #line 16 "numeric/modular/modint_interface.hpp" namespace uni { namespace internal { template<class T> concept modint_family = numeric<T> && has_static_one<T> && has_static_zero<T> && requires (T v, i64 p, typename T::value_type x) { { v.pow(p) } -> std::same_as<T>; { v.inv() } -> std::same_as<T>; { T::raw(x) } -> std::same_as<T>; { v.val() } -> std::same_as<typename T::value_type>; { T::mod() } -> std::same_as<typename T::value_type>; { T::max() } -> std::same_as<typename T::value_type>; T::digits; T::context::dynamic; }; template<class T> concept dynamic_modint_family = modint_family<T> && T::context::dynamic && requires (typename T::value_type v) { T::set_mod(v); }; template<class T> concept static_modint_family = modint_family<T> && (!T::context::dynamic); //&& // requires { // T::is_prime; // }; template<class T> concept modular_reduction = std::default_initializable<T> && std::constructible_from<T, typename T::value_type> && requires (T v, typename T::value_type x, i64 p) { typename T::value_type; T::digits; { T::max() } -> std::same_as<typename T::value_type>; { v.mod() } -> std::same_as<typename T::value_type>; { v.reduce(x) } -> std::same_as<typename T::value_type>; { v.add(x, x) } -> std::same_as<typename T::value_type>; { v.subtract(x, x) } -> std::same_as<typename T::value_type>; { v.multiply(x, x) } -> std::same_as<typename T::value_type>; { v.multiply(x, x) } -> std::same_as<typename T::value_type>; { v.pow(x, p) } -> std::same_as<typename T::value_type>; { v.convert_raw(x) } -> std::same_as<typename T::value_type>; { v.convert(x) } -> std::same_as<typename T::value_type>; { v.revert(x) } -> std::same_as<typename T::value_type>; v.compare(x, x); }; template<class T> concept modular_context = requires { typename T::reductor; typename T::value_type; T::reduction; }; } // namespace internal template<internal::modular_reduction Reduction, typename Reduction::value_type Mod> struct static_modular_context { using reductor = Reduction; using value_type = typename reductor::value_type; static constexpr bool dynamic = false; static constexpr reductor reduction = reductor(Mod); private: using context = static_modular_context; }; template<internal::modular_reduction Reduction, i64 Id> struct dynamic_modular_context { using reductor = Reduction; using value_type = typename reductor::value_type; static constexpr bool dynamic = true; static inline reductor reduction; private: using context = dynamic_modular_context; public: static constexpr void set_mod(const value_type mod) noexcept(NO_EXCEPT) { context::reduction = reductor(mod); } }; template<internal::modular_context> struct modint; template<u32 Mod> using static_builtin_modular_context_32bit = static_modular_context<builtin_reduction_32bit, Mod>; template<u64 Mod> using static_builtin_modular_context_64bit = static_modular_context<builtin_reduction_64bit, Mod>; template<u32 Mod> using static_barrett_modular_context_32bit = static_modular_context<barrett_reduction_32bit, Mod>; template<u64 Mod> using static_barrett_modular_context_64bit = static_modular_context<barrett_reduction_64bit, Mod>; template<u32 Mod> using static_montgomery_modular_context_32bit = static_modular_context<montgomery_reduction_32bit, Mod>; template<u64 Mod> using static_montgomery_modular_context_64bit = static_modular_context<montgomery_reduction_64bit, Mod>; template<u32 Mod> using static_arbitrary_montgomery_modular_context_32bit = static_modular_context<arbitrary_montgomery_reduction_32bit, Mod>; template<u64 Mod> using static_arbitrary_montgomery_modular_context_64bit = static_modular_context<arbitrary_montgomery_reduction_64bit, Mod>; template<u32 Mod> using static_binary_modular_context_32bit = static_modular_context<binary_reduction_32bit, Mod>; template<u64 Mod> using static_binary_modular_context_64bit = static_modular_context<binary_reduction_64bit, Mod>; template<u128 Mod> using static_binary_modular_context_128bit = static_modular_context<binary_reduction_128bit, Mod>; template<u32 Mod> using static_builtin_modint_32bit = modint<static_builtin_modular_context_32bit<Mod>>; template<u64 Mod> using static_builtin_modint_64bit = modint<static_builtin_modular_context_64bit<Mod>>; template<u32 Mod> using static_barrett_modint_32bit = modint<static_barrett_modular_context_32bit<Mod>>; template<u64 Mod> using static_barrett_modint_64bit = modint<static_barrett_modular_context_64bit<Mod>>; template<u32 Mod> using static_montgomery_modint_32bit = modint<static_montgomery_modular_context_32bit<Mod>>; template<u64 Mod> using static_montgomery_modint_64bit = modint<static_montgomery_modular_context_64bit<Mod>>; template<u32 Mod> using static_arbitrary_montgomery_modint_32bit = modint<static_arbitrary_montgomery_modular_context_32bit<Mod>>; template<u64 Mod> using static_arbitrary_montgomery_modint_64bit = modint<static_arbitrary_montgomery_modular_context_64bit<Mod>>; template<u32 Mod> using static_binary_modint_32bit = modint<static_binary_modular_context_32bit<Mod>>; template<u64 Mod> using static_binary_modint_64bit = modint<static_binary_modular_context_64bit<Mod>>; template<u128 Mod> using static_binary_modint_128bit = modint<static_binary_modular_context_128bit<Mod>>; template<i64 Id> using dynamic_builtin_modular_context_32bit = dynamic_modular_context<builtin_reduction_32bit, Id>; template<i64 Id> using dynamic_builtin_modular_context_64bit = dynamic_modular_context<builtin_reduction_64bit, Id>; template<i64 Id> using dynamic_barrett_modular_context_32bit = dynamic_modular_context<barrett_reduction_32bit, Id>; template<i64 Id> using dynamic_barrett_modular_context_64bit = dynamic_modular_context<barrett_reduction_64bit, Id>; template<i64 Id> using dynamic_montgomery_modular_context_32bit = dynamic_modular_context<montgomery_reduction_32bit, Id>; template<i64 Id> using dynamic_montgomery_modular_context_64bit = dynamic_modular_context<montgomery_reduction_64bit, Id>; template<i64 Id> using dynamic_arbitrary_montgomery_modular_context_32bit = dynamic_modular_context<arbitrary_montgomery_reduction_32bit, Id>; template<i64 Id> using dynamic_arbitrary_montgomery_modular_context_64bit = dynamic_modular_context<arbitrary_montgomery_reduction_64bit, Id>; template<i64 Id> using dynamic_binary_modular_context_32bit = dynamic_modular_context<binary_reduction_32bit, Id>; template<i64 Id> using dynamic_binary_modular_context_64bit = dynamic_modular_context<binary_reduction_64bit, Id>; template<i64 Id> using dynamic_binary_modular_context_128bit = dynamic_modular_context<binary_reduction_128bit, Id>; template<i64 Id> using dynamic_builtin_modint_32bit = modint<dynamic_builtin_modular_context_32bit<Id>>; template<i64 Id> using dynamic_builtin_modint_64bit = modint<dynamic_builtin_modular_context_64bit<Id>>; template<i64 Id> using dynamic_barrett_modint_32bit = modint<dynamic_barrett_modular_context_32bit<Id>>; template<i64 Id> using dynamic_barrett_modint_64bit = modint<dynamic_barrett_modular_context_64bit<Id>>; template<i64 Id> using dynamic_montgomery_modint_32bit = modint<dynamic_montgomery_modular_context_32bit<Id>>; template<i64 Id> using dynamic_montgomery_modint_64bit = modint<dynamic_montgomery_modular_context_64bit<Id>>; template<i64 Id> using dynamic_arbitrary_montgomery_modint_32bit = modint<dynamic_arbitrary_montgomery_modular_context_32bit<Id>>; template<i64 Id> using dynamic_arbitrary_montgomery_modint_64bit = modint<dynamic_arbitrary_montgomery_modular_context_64bit<Id>>; template<i64 Id> using dynamic_binary_modint_32bit = modint<dynamic_binary_modular_context_32bit<Id>>; template<i64 Id> using dynamic_binary_modint_64bit = modint<dynamic_binary_modular_context_64bit<Id>>; template<i64 Id> using dynamic_binary_modint_128bit = modint<dynamic_binary_modular_context_128bit<Id>>; template<u32 Mod> using static_modint_32bit = static_builtin_modint_32bit<Mod>; template<u64 Mod> using static_modint_64bit = static_builtin_modint_64bit<Mod>; using modint998244353 = static_modint_32bit<998244353>; using modint1000000007 = static_modint_32bit<1000000007>; using modint_32 = dynamic_barrett_modint_32bit<-1>; using modint_64 = dynamic_barrett_modint_64bit<-1>; template<const unsigned Val, const unsigned Mod = 998244353> const uni::static_modint_32bit<Mod> MINT = Val; template<const unsigned Val, const unsigned Mod = 998244353> const unsigned INV = uni::static_modint_32bit<Mod>{ Val }.inv().val(); template<const unsigned Val, const unsigned Mod = 998244353> const int SINV = uni::static_modint_32bit<Mod>{ Val }.inv().val(); } // namespace uni #line 13 "numeric/internal/primality_test.hpp" namespace uni { namespace internal { //Thanks to: https://github.com/NyaanNyaan/library/blob/master/prime/fast-factorize.hpp namespace fast_factorize_impl { namespace internal { // Miller-Rabin primality test template<modint_family Mint> constexpr bool primality_test(const u64 n, const std::vector<u64>& ws) noexcept(NO_EXCEPT) { if constexpr(dynamic_modint_family<Mint>) Mint::set_mod(n); assert(Mint::mod() == n); const u64 d = (n - 1) >> std::countr_zero(n - 1); const Mint rev = n - 1; for(u64 w : ws) { Mint x = w; if(x == Mint::zero) continue; x = x.pow(d); if(x == Mint::one || x == rev) continue; u64 t = d; while(t != n - 1 && x != Mint::one && x != rev) x *= x, t <<= 1; if(x != rev) return false; } return true; } // Thanks to: https://miller-rabin.appspot.com/ template<modint_family Small, modint_family Large = Small> inline constexpr bool is_prime(const u64 n) noexcept(NO_EXCEPT) { if(n == 0 || n == 1) return false; if(~n & 1UL) return n == 2UL; auto bases = [&]() constexpr noexcept(NO_EXCEPT) -> vector<u64> { if(n < 341531UL) return { 9345883071009581737UL }; else if(n < 1050535501UL) return { 336781006125UL, 9639812373923155UL }; else if(n < 350269456337UL) return { 4230279247111683200UL, 14694767155120705706UL, 16641139526367750375UL }; else if(n < 55245642489451UL) return { 2UL, 141889084524735UL, 1199124725622454117UL, 11096072698276303650UL }; else if(n < 7999252175582851UL) return { 2UL, 4130806001517UL, 149795463772692060UL, 186635894390467037UL, 3967304179347715805UL }; else if(n < 585226005592931977UL) return { 2UL, 123635709730000UL, 9233062284813009UL, 43835965440333360UL, 761179012939631437UL, 1263739024124850375UL }; else return { 2UL, 325UL, 9375UL, 28178UL, 450775UL, 9780504UL, 1795265022UL }; }; if(n <= Small::max()) return primality_test<Small>(n, bases()); else return primality_test<Large>(n, bases()); } } // namespace internal } // namespace fast_factorize_impl using fast_factorize_impl::internal::is_prime; } // namespace internal } // namespace uni #line 2 "numeric/internal/factorize.hpp" #line 10 "numeric/internal/factorize.hpp" #include <random> #line 12 "numeric/internal/factorize.hpp" #line 15 "numeric/internal/factorize.hpp" #line 17 "numeric/internal/factorize.hpp" #line 21 "numeric/internal/factorize.hpp" #line 2 "random/engine.hpp" #line 7 "random/engine.hpp" #line 9 "random/engine.hpp" #line 12 "random/engine.hpp" #line 14 "random/engine.hpp" #line 2 "hash/general_hasher.hpp" #line 7 "hash/general_hasher.hpp" #line 11 "hash/general_hasher.hpp" #line 13 "hash/general_hasher.hpp" namespace uni { template<std::unsigned_integral R, std::integral T> constexpr R shrink(T x) noexcept(NO_EXCEPT) { constexpr int DIGITS_R = std::numeric_limits<R>::digits; constexpr int DIGITS_T = std::numeric_limits<R>::digits; REPD(digits, DIGITS_R, DIGITS_T, DIGITS_R) { x = (x >> digits) ^ uni::lower_bits(x, digits); } return x; } // Thanks to: https://gist.github.com/badboy/6267743 template<class T> constexpr u32 hash32(T x) { if constexpr(std::integral<T>) { if constexpr(std::signed_integral<T>) return hash32(to_unsigned(x)); constexpr int DIGITS_T = std::numeric_limits<T>::digits; if constexpr(DIGITS_T <= 32) { auto h = static_cast<u32>(x); h = ~h + (h << 15); h ^= (h >> 12); h += (h << 2); h ^= (h >> 4); h *= 2057; h ^= (h >> 16); return h; } else if constexpr(DIGITS_T <= 64) { auto h = static_cast<u64>(x); h = (~h) + (h << 18); h ^= (h >> 31); h *= 21; h ^= (h >> 11); h += (h << 6); h ^= (h >> 22); return static_cast<u32>(h); } else { return hash32(hash64(x)); } } else { return hash32(std::hash<T>{}(x)); } } template<class T> constexpr u64 hash64(T x) { if constexpr(std::integral<T>) { if constexpr(std::signed_integral<T>) return hash64(to_unsigned(x)); constexpr int DIGITS_T = std::numeric_limits<T>::digits; if constexpr(DIGITS_T <= 64) { auto h = static_cast<u64>(x); h = (~h) + (h << 21); h ^= (h >> 24); h *= 265; h ^= (h >> 14); h *= 21; h ^= (h >> 28); h += h << 31; return h; } else { return hash64(shrink<u64>(x)); } } else { return hash64(std::hash<T>{}(x)); } } template<class T> struct hash { inline constexpr auto operator()(const T& key) const noexcept(NO_EXCEPT) { return static_cast<std::size_t>(uni::hash64(key)); } }; } // namespace uni #line 16 "random/engine.hpp" // Thanks to: https://prng.di.unimi.it/ namespace uni { namespace internal { template<class Derived, class ResultType> struct random_engine { using result_type = ResultType; static constexpr result_type MIN = std::numeric_limits<result_type>::min(); static constexpr result_type MAX = std::numeric_limits<result_type>::max(); static constexpr result_type min() noexcept(NO_EXCEPT) { return MIN; } static constexpr result_type max() noexcept(NO_EXCEPT) { return MAX; } template<std::unsigned_integral T = result_type> constexpr random_engine(const T _seed = 0) noexcept(NO_EXCEPT) { static_cast<Derived*>(this)->seed(_seed); }; inline constexpr result_type operator()() noexcept(NO_EXCEPT) { return static_cast<Derived*>(this)->next(); } }; const i64 INTERNAL_RANDOM_GENERATOR_ID = -(1UL << 60); }; // namespace internal constexpr float to_float(const std::uint32_t x) noexcept(NO_EXCEPT) { return float(x >> 8) * 0x1.0p-24f; } constexpr double to_double(const std::uint64_t x) noexcept(NO_EXCEPT) { return double(x >> 11) * 0x1.0p-53; } struct mulberry32 : internal::random_engine<mulberry32, std::uint32_t> { using internal::random_engine<mulberry32, std::uint32_t>::random_engine; private: std::uint32_t _x; public: template<std::unsigned_integral T> inline constexpr void seed(const T x) noexcept(NO_EXCEPT) { this->_x = x; } inline constexpr std::uint32_t next() noexcept(NO_EXCEPT) { std::uint32_t z = (this->_x += 0x6D2B79F5U); z = (z ^ (z >> 15)) * (z | 1U); z ^= z + (z ^ (z >> 7)) * (z | 61U); return static_cast<std::uint32_t>(z ^ (z >> 14)); } }; struct splitmix64 : internal::random_engine<splitmix64, std::uint64_t> { using internal::random_engine<splitmix64, std::uint64_t>::random_engine; private: std::uint64_t _x; public: template<std::unsigned_integral T> inline constexpr void seed(const T x) noexcept(NO_EXCEPT) { this->_x = x; } inline constexpr std::uint64_t next() noexcept(NO_EXCEPT) { std::uint64_t z = (this->_x += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; return z ^ (z >> 31); } }; // xoroshiro64** struct xoroshiro64ss : internal::random_engine<xoroshiro64ss, std::uint32_t> { using internal::random_engine<xoroshiro64ss, std::uint32_t>::random_engine; private: std::uint32_t s[2]; public: template<std::unsigned_integral T> inline constexpr void seed(const T _seed) noexcept(NO_EXCEPT) { mulberry32 gen32(hash32(_seed)); this->s[0] = gen32(); this->s[1] = gen32(); } inline constexpr std::uint32_t next() noexcept(NO_EXCEPT) { const std::uint32_t s0 = this->s[0]; std::uint32_t s1 = this->s[1]; const std::uint32_t res = std::rotl(s0 * 0x9E3779BBU, 5) * 5; s1 ^= s0; this->s[0] = std::rotl(s0, 26) ^ s1 ^ (s1 << 9); this->s[1] = std::rotl(s1, 13); return res; } }; struct xoroshiro128ss : internal::random_engine<xoroshiro128ss, std::uint64_t> { using internal::random_engine<xoroshiro128ss, std::uint64_t>::random_engine; private: std::uint64_t s[2]; public: template<std::unsigned_integral T> inline constexpr void seed(const T _seed) noexcept(NO_EXCEPT) { splitmix64 gen64(hash32(_seed)); this->s[0] = gen64(); this->s[1] = gen64(); } inline constexpr std::uint64_t next() noexcept(NO_EXCEPT) { const uint64_t s0 = this->s[0]; uint64_t s1 = this->s[1]; const uint64_t res = std::rotl(s0 * 5, 7) * 9; s1 ^= s0; this->s[0] = std::rotl(s0, 24) ^ s1 ^ (s1 << 16); this->s[1] = std::rotl(s1, 37); return res; } }; struct xoroshiro128pp : internal::random_engine<xoroshiro128pp, std::uint64_t> { using internal::random_engine<xoroshiro128pp, std::uint64_t>::random_engine; private: std::uint64_t s[2]; public: template<std::unsigned_integral T> inline constexpr void seed(const T _seed) noexcept(NO_EXCEPT) { splitmix64 gen64(hash32(_seed)); this->s[0] = gen64(); this->s[1] = gen64(); } inline constexpr std::uint64_t next() noexcept(NO_EXCEPT) { const std::uint64_t s0 = this->s[0]; std::uint64_t s1 = this->s[1]; const std::uint64_t res = std::rotl(s0 + s1, 17) + s0; s1 ^= s0; this->s[0] = std::rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b this->s[1] = std::rotl(s1, 28); // c return res; } }; // xoroshiro128+ struct xoroshiro128p : internal::random_engine<xoroshiro128p, std::uint64_t> { using internal::random_engine<xoroshiro128p, std::uint64_t>::random_engine; private: std::uint64_t s[2]; public: template<std::unsigned_integral T> inline constexpr void seed(const T _seed) noexcept(NO_EXCEPT) { splitmix64 gen64(hash64(_seed)); this->s[0] = gen64(); this->s[1] = gen64(); } inline constexpr std::uint64_t next() noexcept(NO_EXCEPT) { const std::uint64_t s0 = this->s[0]; std::uint64_t s1 = this->s[1]; const std::uint64_t res = s0 + s1; s1 ^= s0; this->s[0] = std::rotl(s0, 24) ^ s1 ^ (s1 << 16); this->s[1] = std::rotl(s1, 37); return res; } }; struct xoroshiro64s : internal::random_engine<xoroshiro64s, std::uint32_t> { using internal::random_engine<xoroshiro64s, std::uint32_t>::random_engine; private: std::uint32_t s[2]; public: template<std::unsigned_integral T> inline constexpr void seed(const T _seed) noexcept(NO_EXCEPT) { mulberry32 gen32(hash32(_seed)); this->s[0] = gen32(); this->s[1] = gen32(); } inline constexpr std::uint32_t next() noexcept(NO_EXCEPT) { const std::uint32_t s0 = s[0]; std::uint32_t s1 = s[1]; const std::uint32_t res = s0 * 0x9E3779BB; s1 ^= s0; s[0] = std::rotl(s0, 26) ^ s1 ^ (s1 << 9); s[1] = std::rotl(s1, 13); return res; } }; using random_engine_32bit = xoroshiro64ss; using random_engine_64bit = xoroshiro128pp; using random_engine_float = xoroshiro64s; using random_engine_double = xoroshiro128p; random_engine_32bit randi32; random_engine_64bit randi64; float randf() { static random_engine_float gen; return to_float(gen()); } double randd() { static random_engine_double gen; return to_double(gen()); } } // namespace uni #line 23 "numeric/internal/factorize.hpp" namespace uni { namespace internal { //Thanks to: https://github.com/NyaanNyaan/library/blob/master/prime/fast-factorize.hpp namespace fast_factorize_impl { namespace internal { // Pollard's rho algorithm template<modint_family Mint, class T> T find_factor(const T n) noexcept(NO_EXCEPT) { if(~n & 1) return 2; if(is_prime<Mint>(n)) return n; assert(static_cast<u64>(Mint::mod()) == n); Mint rr; auto f = [&](const Mint& x) noexcept(NO_EXCEPT) { return x * x + rr; }; static random_engine_64bit rand(std::random_device{}()); auto rand_ = [&]() noexcept(NO_EXCEPT) { return rand() % (n - 2) + 2; }; while(true) { Mint x, y, ys, q = Mint::one; rr = rand_(), y = rand_(); T g = 1; constexpr int m = 128; for(int r = 1; g == 1; r <<= 1) { x = y; for(int i = 0; i < r; ++i) y = f(y); for(int k = 0; g == 1 && k < r; k += m) { ys = y; for(int i = 0; i < m && i < r - k; ++i) q *= x - (y = f(y)); g = uni::binary_gcd(q.val(), n); } } if(g == n) { do { g = uni::binary_gcd((x - (ys = f(ys))).val(), n); } while(g == 1); } if(g != n) return g; } assert(false); } template<modint_family Small, modint_family Large, class R> void factorize(const u64 n, R *const res) noexcept(NO_EXCEPT) { if(n <= 1) return; u64 p; if constexpr(std::same_as<Small, Large>) p = find_factor<Small, typename Small::value_type>(n); else { if(n <= Small::max()) p = find_factor<Small, typename Small::value_type>(n); else p = find_factor<Large, typename Large::value_type>(n); } if(p == static_cast<u64>(n)) { res->emplace_back(p); return; } factorize<Small, Large>(p, res); factorize<Small, Large>(n / p, res); } } // namespace internal } // namespace fast_factorize_impl using fast_factorize_impl::internal::factorize; } // namespace internal } // namespace uni #line 2 "numeric/internal/divisors.hpp" #line 8 "numeric/internal/divisors.hpp" #line 12 "numeric/internal/divisors.hpp" namespace uni { namespace internal { //Thanks to: https://github.com/NyaanNyaan/library/blob/master/prime/fast-factorize.hpp template<modint_family Small, modint_family Large, class R> void divisors(const u64 n, R *const res) noexcept(NO_EXCEPT) { if(n == 0) return; std::vector<u64> facts; factorize<Small, Large>(n, &facts); std::ranges::sort(facts); std::vector<std::pair<u64, int>> v; for(auto &p : facts) { if(v.empty() || v.back().first != p) { v.emplace_back(p, 1); } else { v.back().second++; } } using value_type = std::ranges::range_value_t<R>; const auto size = std::ranges::ssize(v); auto f = [&](auto rc, int i, value_type x) noexcept(NO_EXCEPT) -> void { if(i == size) { res->push_back(x); return; } for(int j = v[i].second; ; --j) { rc(rc, i + 1, x); if(j == 0) break; x *= static_cast<value_type>(v[i].first); } }; f(f, 0, 1); } } // namespace internal } // namespace uni #line 2 "numeric/internal/primitive_root.hpp" #line 8 "numeric/internal/primitive_root.hpp" #line 11 "numeric/internal/primitive_root.hpp" #line 13 "numeric/internal/primitive_root.hpp" #line 16 "numeric/internal/primitive_root.hpp" #line 18 "numeric/internal/primitive_root.hpp" namespace uni { namespace internal { // Thanks to: https://37zigen.com/primitive-root/ template<modint_family Small, modint_family Large, modint_family Mint, std::unsigned_integral T> T primitive_root(const T p) noexcept(NO_EXCEPT) { std::vector<T> pows; factorize<Small, Large>(p - 1, &pows); { std::ranges::sort(pows); const auto rest = std::ranges::unique(pows); pows.erase(ALL(rest)); } ITRR(pow, pows) pow = (p - 1) / pow; if constexpr(dynamic_modint_family<Mint>) Mint::set_mod(p); assert(Mint::mod() == p); static random_engine_64bit rand; while(true) { const Mint x = rand(); if(x == Mint::zero) continue; bool ok = true; ITR(pow, pows) { if(x.pow(pow) == Mint::one) { ok = false; break; } } if(ok) return x.val(); } return 0; } // Thanks to: atcoder::internal::primitive_root_constexpr template<static_modint_family Mint> constexpr u32 primitive_root_constexpr(u32 m) { assert(Mint::mod() == m); u32 divs[20]{}; divs[0] = 2; u32 cnt = 1; u64 x = (m - 1) / 2; while(x % 2 == 0) x /= 2; for(u64 i = 3; i * i <= x; i += 2) { if(x % i == 0) { divs[cnt++] = i; while(x % i == 0) x /= i; } } if(x > 1) divs[cnt++] = x; for(u32 g = 2; ; g++) { bool ok = true; REP(i, cnt) { if(Mint{ g }.pow((m - 1) / divs[i]) == 1) { ok = false; break; } } if(ok) return g; } } template<modint_family Small, modint_family Large = Small, std::integral Res = u64, bool FORCE_RANDOM = false> constexpr Res primitive_root(const u64 p) noexcept(NO_EXCEPT) { if constexpr(!FORCE_RANDOM) { if(p == 2) return 1; if(p == 167772161) return 3; if(p == 469762049) return 3; if(p == 754974721) return 11; if(p == 998244353) return 3; if(p == (UINT64_C(1) << 61) - 1) return 37; } if(std::is_constant_evaluated()) { if constexpr(static_modint_family<Small> && std::same_as<Small, Large> && Small::mod() < (1U << 31)) { assert(p <= std::numeric_limits<u32>::max()); return primitive_root_constexpr<Small>(p); } assert(false); } else { if(p <= Small::max()) return primitive_root<Small, Large, Small, typename Small::value_type>(p); else return primitive_root<Small, Large, Large, typename Large::value_type>(p); } } } // namespace internal } // namespace uni #line 2 "numeric/modular/modint.hpp" #line 7 "numeric/modular/modint.hpp" #line 10 "numeric/modular/modint.hpp" #line 13 "numeric/modular/modint.hpp" #line 15 "numeric/modular/modint.hpp" #line 17 "numeric/modular/modint.hpp" namespace uni { namespace internal { template<class, bool> struct modint_base {}; template<class Mint> struct modint_base<Mint, false> { static constexpr Mint zero = Mint::_raw(0); static constexpr Mint one = Mint::_one(); }; template<class Mint> struct modint_base<Mint, true> { static constexpr Mint zero = Mint::_raw(0); static inline Mint one = Mint::_one(); }; } // internal template<internal::modular_context Context> struct modint : internal::modint_base<modint<Context>, Context::dynamic> { using value_type = typename Context::value_type; using context = Context; private: using base = internal::modint_base<modint, context::dynamic>; friend base; value_type _val = 0; static constexpr auto _raw(const value_type v) noexcept(NO_EXCEPT) { modint res; res._val = v; return res; } static constexpr auto _one() noexcept(NO_EXCEPT) requires internal::has_static_one<typename modint::context::reductor> { return modint::_raw(modint::context::reduction.one); } static constexpr auto _one() noexcept(NO_EXCEPT) requires (!internal::has_static_one<typename modint::context::reductor>) { return modint::_raw(1); } public: static constexpr int digits = modint::context::reductor::digits; static constexpr value_type max() noexcept { return modint::context::reductor::max(); } static constexpr void set_mod(const value_type mod) noexcept(NO_EXCEPT) requires requires(value_type mod) { modint::context::set_mod(mod); } { modint::context::set_mod(mod); modint::one = modint::_one(); } static constexpr auto mod() noexcept(NO_EXCEPT) { return modint::context::reduction.mod(); } static constexpr auto raw(const value_type v) noexcept(NO_EXCEPT) { modint res; res._val = modint::context::reduction.convert_raw(v); return res; }; constexpr modint() noexcept = default; template<std::integral T> constexpr modint(const T v) noexcept(NO_EXCEPT) : _val(modint::context::reduction.convert(v)) {} inline constexpr auto val() const noexcept(NO_EXCEPT) { return modint::context::reduction.revert(this->_val); } inline constexpr explicit operator value_type() const noexcept(NO_EXCEPT) { return this->_val; } inline constexpr auto& operator+=(const modint& rhs) noexcept(NO_EXCEPT) { this->_val = modint::context::reduction.add(this->_val, rhs._val); return *this; } inline constexpr auto& operator-=(const modint& rhs) noexcept(NO_EXCEPT) { this->_val = modint::context::reduction.subtract(this->_val, rhs._val); return *this; } inline constexpr auto& operator*=(const modint& rhs) noexcept(NO_EXCEPT) { this->_val = modint::context::reduction.multiply(this->_val, rhs._val); return *this; } inline constexpr auto& operator/=(const modint& rhs) noexcept(NO_EXCEPT) { return *this *= rhs.inv(); } template<std::integral K> constexpr auto pow(const K n) const noexcept(NO_EXCEPT) { if constexpr(std::signed_integral<K>) assert(n >= 0); return modint::_raw(modint::context::reduction.pow(this->_val, n)); } constexpr auto inv() const noexcept(NO_EXCEPT) { using signed_value_type = std::make_signed_t<value_type>; signed_value_type x = this->val(), y = modint::mod(), u = 1, v = 0; while(y > 0) { signed_value_type t = x / y; std::swap(x -= t * y, y); std::swap(u -= t * v, v); } assert(x == 1); if(u < 0) u += v / x; return modint::raw(u); } friend inline constexpr auto operator<=>(const modint& lhs, const modint& rhs) noexcept(NO_EXCEPT) { return modint::context::reduction.compare(lhs._val, rhs._val); } friend inline constexpr bool operator==(const modint& lhs, const modint& rhs) noexcept(NO_EXCEPT) { return lhs <=> rhs == 0; } inline constexpr auto& operator++() noexcept(NO_EXCEPT) { return *this += modint::one; } inline constexpr auto& operator--() noexcept(NO_EXCEPT) { return *this -= modint::one; } inline constexpr auto operator++(int) noexcept(NO_EXCEPT) { const modint res = *this; return ++*this, res; } inline constexpr auto operator--(int) noexcept(NO_EXCEPT) { const modint res = *this; return --*this, res; } inline constexpr auto operator+() const noexcept(NO_EXCEPT) { return *this; } inline constexpr auto operator-() const noexcept(NO_EXCEPT) { return modint::zero - *this; } friend inline constexpr auto operator+(modint lhs, const modint& rhs) noexcept(NO_EXCEPT) { return lhs += rhs; } friend inline constexpr auto operator-(modint lhs, const modint& rhs) noexcept(NO_EXCEPT) { return lhs -= rhs; } friend inline constexpr auto operator*(modint lhs, const modint& rhs) noexcept(NO_EXCEPT) { return lhs *= rhs; } friend inline constexpr auto operator/(modint lhs, const modint& rhs) noexcept(NO_EXCEPT) { return lhs /= rhs; } }; } // namespace uni #line 17 "numeric/fast_prime.hpp" namespace uni { namespace internal { constexpr i64 INTERNAL_MODINT_ID = -(1L << 62); inline constexpr bool is_prime(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); return is_prime<uni::dynamic_montgomery_modint_32bit<INTERNAL_MODINT_ID>, uni::dynamic_montgomery_modint_64bit<INTERNAL_MODINT_ID>>(n); } inline auto factorize(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); vector<i64> res; factorize<uni::dynamic_montgomery_modint_32bit<INTERNAL_MODINT_ID>, uni::dynamic_montgomery_modint_64bit<INTERNAL_MODINT_ID>>(n, &res); return res; } inline auto divisors(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); vector<i64> res; divisors<uni::dynamic_montgomery_modint_32bit<INTERNAL_MODINT_ID>, uni::dynamic_montgomery_modint_64bit<INTERNAL_MODINT_ID>>(n, &res); std::ranges::sort(res); return res; } template<bool FORCE_RANDOM = false> inline auto primitive_root(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); return primitive_root<uni::dynamic_montgomery_modint_32bit<INTERNAL_MODINT_ID>, uni::dynamic_montgomery_modint_64bit<INTERNAL_MODINT_ID>, i64, FORCE_RANDOM>(n); } } // namespace internal using internal::is_prime; using internal::divisors; using internal::primitive_root; inline vector<i64> factorize(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); auto res = internal::factorize(n); std::ranges::sort(res); return res; } inline set<i64> prime_factors(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); const auto factors = factorize(n); set<i64> res(ALL(factors)); return res; } inline map<i64,i64> count_factors(const i64 n) noexcept(NO_EXCEPT) { assert(n >= 0); map<i64,i64> mp; for(auto &x : internal::factorize(n)) mp[x]++; return mp; } } // namespace uni #line 15 "algebraic/rolling_hash.hpp" #line 17 "algebraic/rolling_hash.hpp" namespace uni { namespace algebraic { template<uni::internal::modint_family ValueType, typename ValueType::value_type BASE> struct rolling_hash_impl { using value_type = ValueType; inline static value_type base; private: value_type _value = 0, _power = 1; public: rolling_hash_impl(const value_type& value, const value_type& power) noexcept(NO_EXCEPT) : _value(value), _power(power) { if(rolling_hash_impl::base == 0) { if constexpr(BASE == 0) { rolling_hash_impl::base = uni::primitive_root<true>(value_type::mod()); } else if constexpr(BASE < 0) { random_engine_64bit random(std::random_device{}()); rolling_hash_impl::base = static_cast<value_type>(random() % value_type::mod()); } else { rolling_hash_impl::base = BASE; } } } rolling_hash_impl(const value_type& value) noexcept(NO_EXCEPT) : rolling_hash_impl(value, 0) { this->_power = rolling_hash_impl::base; }; rolling_hash_impl() noexcept = default; inline auto power() const noexcept(NO_EXCEPT) { return this->_power; } inline auto val() const noexcept(NO_EXCEPT) { return this->_value; } friend inline bool operator==(const rolling_hash_impl& lhs, const rolling_hash_impl& rhs) noexcept(NO_EXCEPT) { return lhs._power == rhs._power && lhs._value == rhs._value; } friend inline auto operator<=>(const rolling_hash_impl& lhs, const rolling_hash_impl& rhs) noexcept(NO_EXCEPT) { const auto comp_power = lhs._power <=> rhs._power; if(comp_power != 0) return comp_power; return lhs._value <=> rhs._value; } }; template< bool REVERSE = false, uni::internal::modint_family T = uni::static_modint_64bit<(1UL << 61) - 1>, typename T::value_type BASE = 0 > struct rolling_hash : base<rolling_hash_impl<T, BASE>>, scalar_multipliable<rolling_hash<REVERSE, T, BASE>>::automatic, associative { using base<rolling_hash_impl<T, BASE>>::base; rolling_hash(const T& v) : base<rolling_hash_impl<T, BASE>>(v) {} template<class U> requires ( (!std::same_as<std::remove_cvref_t<U>, T>) && (!std::constructible_from<rolling_hash_impl<T, BASE>, U>) ) rolling_hash(U&& v) : base<rolling_hash_impl<T, BASE>>(hash64(std::forward<U>(v))) {} friend inline auto operator+(const rolling_hash& lhs, const rolling_hash& rhs) noexcept(NO_EXCEPT) { const auto power = lhs->power() * rhs->power(); if constexpr(REVERSE) return rolling_hash({ lhs->val() * rhs->power() + rhs->val(), power }); return rolling_hash({ lhs->val() + rhs->val() * lhs->power(), power }); } inline auto operator-() noexcept(NO_EXCEPT) { const auto power_inv = this->val().power().inv(); return rolling_hash({ -this->val().val() * power_inv, power_inv }); } }; } // namespace algebraic } // namespace uni #line 10 "action/range_sequence_hash.hpp" namespace uni { namespace actions { template< bool REVERSE = false, uni::internal::modint_family T = uni::static_modint_64bit<(1UL << 61) - 1>, typename T::value_type BASE = 0 > using range_sequence_hash = make_operatable_t<uni::algebraic::rolling_hash<REVERSE, T, BASE>>; static_assert(internal::operand_only_action<range_sequence_hash<false>>); static_assert(internal::operand_only_action<range_sequence_hash<true>>); } // namespace actions } // namespace uni #line 2 "action/range_set.hpp" #line 6 "action/range_set.hpp" #line 2 "algebraic/assignment.hpp" #line 4 "algebraic/assignment.hpp" #line 7 "algebraic/assignment.hpp" namespace uni { namespace algebraic { template<class T> struct assignment : base<std::optional<T>>, scalar_multipliable<assignment<T>>::identity, associative { using base<std::optional<T>>::base; friend inline assignment operator+(const assignment& lhs, const assignment& rhs) noexcept(NO_EXCEPT) { if(lhs->has_value()) return lhs; return rhs; } }; } // namespace algebraic } // namespace uni #line 9 "action/range_set.hpp" namespace uni { namespace actions { template<class T> struct range_set : base<algebraic::assignment<T>> { using operand = algebraic::null<T>; using operation = algebraic::assignment<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f->value_or(x.val()); } }; static_assert(internal::full_action<range_set<int>>); } // namesapce actions } // namespace uni #line 2 "action/range_set_range_composition.hpp" #line 5 "action/range_set_range_composition.hpp" #line 9 "action/range_set_range_composition.hpp" #line 12 "action/range_set_range_composition.hpp" namespace uni { namespace actions { template<class T, bool REVERSE = false> struct range_set_range_composition : base<algebraic::assignment<std::pair<T, T>>> { using base<algebraic::assignment<std::pair<T, T>>>::base; using operand = algebraic::affine<T, REVERSE>; using operation = algebraic::assignment<std::pair<T, T>>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f->value_or(std::make_pair(x->first, x->second)); } }; static_assert(internal::full_action<range_set_range_composition<int>>); } // namespace actions } // namespace uni #line 2 "action/range_set_range_max.hpp" #line 5 "action/range_set_range_max.hpp" #line 7 "action/range_set_range_max.hpp" #line 10 "action/range_set_range_max.hpp" namespace uni { namespace actions { template<class T> struct range_set_range_max : base<algebraic::assignment<T>> { using operand = algebraic::maximum<T>; using operation = algebraic::assignment<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f->value_or(x.val()); } }; static_assert(internal::full_action<range_set_range_max<int>>); } // namespace actions } // namespace uni #line 2 "action/range_set_range_min.hpp" #line 5 "action/range_set_range_min.hpp" #line 7 "action/range_set_range_min.hpp" #line 10 "action/range_set_range_min.hpp" namespace uni { namespace actions { template<class T> struct range_set_range_min : base<algebraic::assignment<T>> { using operand = algebraic::minimum<T>; using operation = algebraic::assignment<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f->value_or(x.val()); } }; static_assert(internal::full_action<range_set_range_min<int>>); } // namespace actions } // namespace uni #line 2 "action/range_set_range_sum.hpp" #line 5 "action/range_set_range_sum.hpp" #line 7 "action/range_set_range_sum.hpp" #line 10 "action/range_set_range_sum.hpp" namespace uni { namespace actions { template<class T> struct range_set_range_sum { using operand = algebraic::addition<T>; using operation = algebraic::assignment<T>; static operand mapping(const operation& f, const operand& x) noexcept(NO_EXCEPT) { return f->value_or(x.val()); } static auto power(const operation& x, const uni::internal::size_t length) noexcept(NO_EXCEPT) { if(x->has_value()) return operation(x->operator*() * length); return x; } }; static_assert(internal::full_action<range_set_range_sum<int>>); } // namespace actions } // namespace uni #line 2 "action/range_sum.hpp" #line 6 "action/range_sum.hpp" #line 8 "action/range_sum.hpp" namespace uni { namespace actions { template<class T> using range_sum = make_operatable_t<uni::algebraic::addition<T>>; static_assert(internal::operand_only_action<range_sum<int>>); } // namespace actions } // namespace uni #line 2 "include/adaptors.hpp" #line 4 "include/adaptors.hpp" #line 2 "adaptor/array.hpp" #line 6 "adaptor/array.hpp" #line 9 "adaptor/array.hpp" namespace uni { template<class T, int N> using array = internal::advanced_container<std::array<T,N>>; } // namespace uni #line 2 "adaptor/auto_expander.hpp" #line 7 "adaptor/auto_expander.hpp" #line 11 "adaptor/auto_expander.hpp" namespace uni { template<class Container> struct auto_expander : Container { using size_type = Container::size_type; public: template<class... Args> explicit auto_expander(Args&&... args) noexcept(NO_EXCEPT) : Container(std::forward<Args>(args)...) {} inline auto& operator[](const size_type pos) noexcept(NO_EXCEPT) { if(this->size() <= pos) this->Container::resize(pos + 1); return this->Container::operator[](pos); } }; } #line 2 "adaptor/deque_by_stack.hpp" #line 9 "adaptor/deque_by_stack.hpp" #line 12 "adaptor/deque_by_stack.hpp" #line 14 "adaptor/deque_by_stack.hpp" namespace uni { template<class Front, class Back = Front> struct deque_by_stack { static_assert(std::same_as<typename Front::value_type, typename Back::value_type>); static_assert(std::common_reference_with<typename Front::size_type, typename Back::size_type>); using value_type = Front::value_type; using size_type = std::common_type_t<typename Front::size_type, typename Back::size_type>; protected: Front _front; Back _back; private: template<std::ptrdiff_t OFFSET> inline void _distribute() noexcept(NO_EXCEPT) { if(this->empty()) return; std::vector<value_type> temp; temp.reserve(this->size()); if(this->_front.empty()) { while(!this->_back.empty()) { temp.push_back(this->_back.top()); this->_back.pop(); } std::ranges::reverse(temp); } else if(this->_back.empty()) { while(!this->_front.empty()) { temp.push_back(this->_front.top()); this->_front.pop(); } } else { return; } assert(this->empty()); const auto size = std::ranges::ssize(temp); const auto mid = (size + OFFSET) / 2; REPD(i, mid) this->_front.push(temp[i]); REP(i, mid, size) this->_back.push(temp[i]); } public: deque_by_stack() noexcept = default; inline bool empty() const noexcept(NO_EXCEPT) { return this->_front.empty() && this->_back.empty(); } inline auto size() const noexcept(NO_EXCEPT) { return this->_front.size() + this->_back.size(); } inline decltype(auto) front() const noexcept(NO_EXCEPT) { this->_distribute<1>(); assert(!this->_front.empty()); return this->_front.top(); } inline decltype(auto) back() const noexcept(NO_EXCEPT) { this->_distribute<0>(); assert(!this->_back.empty()); return this->_back.top(); } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline decltype(auto) front_or(T&& val) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(val)); else return this->front(); } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline decltype(auto) back_or(T&& val) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(val)); else return this->back(); } inline auto& clear() noexcept(NO_EXCEPT) { this->_front.clear(), this->_back.clear(); return *this; } template<std::convertible_to<value_type> T = value_type> inline auto& push_front(T&& val) noexcept(NO_EXCEPT) { this->_front.push(std::forward<T>(val)); return *this; } template<std::convertible_to<value_type> T = value_type> inline auto& push_back(T&& val) noexcept(NO_EXCEPT) { this->_back.push(std::forward<T>(val)); return *this; } template<class... Args> inline decltype(auto) emplace_front(Args&&... args) noexcept(NO_EXCEPT) { return this->_front.emplace(std::forward<Args>(args)...); } template<class... Args> inline decltype(auto) emplace_back(Args&&... args) noexcept(NO_EXCEPT) { return this->_back.emplace(std::forward<Args>(args)...); } auto& pop_front() noexcept(NO_EXCEPT) { this->_distribute<1>(); assert(!this->_front.empty()); this->_front.pop(); return *this; } auto& pop_back() noexcept(NO_EXCEPT) { this->_distribute<0>(); assert(!this->_back.empty()); this->_back.pop(); return *this; } }; } // namespace uni #line 2 "adaptor/io.hpp" #include <regex> #line 2 "adaptor/internal/input.hpp" #line 12 "adaptor/internal/input.hpp" #line 15 "adaptor/internal/input.hpp" #line 18 "adaptor/internal/input.hpp" #line 20 "adaptor/internal/input.hpp" #line 22 "adaptor/internal/input.hpp" #line 24 "adaptor/internal/input.hpp" namespace uni { template<std::derived_from<std::ios_base> Source = std::istream> struct input_adaptor { using source_type = Source; private: template<class T> requires std::derived_from<T, std::valarray<typename T::value_type>> auto _set(uni::internal::resolving_rank<6>, T& val) noexcept(NO_EXCEPT) -> int { this->operator()(ALL(val)); return 0; } template<class T> requires requires (source_type& in, T& val) { in >> val; } int _set(uni::internal::resolving_rank<5>, T& val) noexcept(NO_EXCEPT) { *this->in >> val; return 0; } template<std::ranges::range T> int _set(uni::internal::resolving_rank<4>, T& val) noexcept(NO_EXCEPT) { this->operator()(std::ranges::begin(val), std::ranges::end(val)); return 0; } template<class T> requires requires (T& val) { val.first; val.second; } int _set(uni::internal::resolving_rank<3>, T& val) noexcept(NO_EXCEPT) { *this >> val.first >> val.second; return 0; } template<class T> requires requires (T& val) { std::get<0>(val); } int _set(uni::internal::resolving_rank<2>, T& val) noexcept(NO_EXCEPT) { tuple_for_each([this](auto&& v) { *this >> v; }, val); return 0; } template<uni::internal::modint_family T> int _set(uni::internal::resolving_rank<1>, T& val) noexcept(NO_EXCEPT) { std::int64_t v; std::cin >> v; val = { v }; return 0; } template<class T> requires requires { typename T::value_type; } int _set(uni::internal::resolving_rank<0>, T& val) noexcept(NO_EXCEPT) { typename T::value_type v; *this >> v; val = { v }; return 0; } protected: template<class T> source_type *set(T& val) noexcept(NO_EXCEPT) { this->_set(uni::internal::resolving_rank<10>{}, val); return this->in; } template<class T> source_type *set(T&& _val) noexcept(NO_EXCEPT) { T val = _val; this->_set(uni::internal::resolving_rank<10>{}, val); return this->in; } public: using char_type = typename source_type::char_type; source_type *in; input_adaptor(source_type *_in = &std::cin) noexcept(NO_EXCEPT) : in(_in) {} template<class T> inline input_adaptor& operator>>(T&& s) noexcept(NO_EXCEPT) { this->set(std::forward<T>(s)); return *this; } template<class T> inline T one() noexcept(NO_EXCEPT) { T val; *this >> val; return val; } template<class T> inline auto& operator()(T& val) noexcept(NO_EXCEPT) { *this >> val; return *this; } template<class T, class... Args> inline auto& operator()(T& head, Args&... tail) noexcept(NO_EXCEPT) { *this >> head; this->operator()(tail...); return *this; } template<std::input_or_output_iterator I, std::sentinel_for<I> S> inline auto& operator()(I first, S last) noexcept(NO_EXCEPT) { for(I itr=first; itr!=last; ++itr) *this >> *itr; return *this; } explicit operator bool() const noexcept(NO_EXCEPT) { return (bool)*this->in; } }; } // namespace uni #line 2 "adaptor/internal/output.hpp" #line 11 "adaptor/internal/output.hpp" #line 15 "adaptor/internal/output.hpp" namespace uni { template<class Destination = std::ostream> struct output_adaptor { using destination_type = Destination; private: template<class T> requires requires (destination_type& out, T val) { out << val; } int _put(uni::internal::resolving_rank<5>, T&& val) noexcept(NO_EXCEPT) { *this->out << std::forward<T>(val); return 0; } template<class T> requires requires (T&& val) { val.val(); } int _put(uni::internal::resolving_rank<4>, T&& val) noexcept(NO_EXCEPT) { this->put(val.val()); return 0; } template<std::ranges::input_range T> int _put(uni::internal::resolving_rank<3>, T&& val) noexcept(NO_EXCEPT) { (*this)(std::ranges::begin(val), std::ranges::end(val), false); return 0; } template<class T> requires requires (T&& val) { val.first; val.second; } int _put(uni::internal::resolving_rank<2>, T&& val) noexcept(NO_EXCEPT) { *this << val.first, this->put_separator(); *this << val.second; return 0; } template<class T> requires requires (T&& val) { std::get<0>(val); } auto _put(uni::internal::resolving_rank<1>, T&& val) noexcept(NO_EXCEPT) { std::apply([this](const auto&... args) constexpr { ((*this << args, this->put_separator()), ...); }, std::forward<T>(val)); return 0; } template<std::input_or_output_iterator T> int _put(uni::internal::resolving_rank<0>, T&& val) noexcept(NO_EXCEPT) { (*this)(*std::forward<T>(val)); return 0; } protected: template<class T> destination_type* put(T&& val) noexcept(NO_EXCEPT){ this->_put(uni::internal::resolving_rank<10>{}, std::forward<T>(val)); return this->out; } public: using char_type = typename destination_type::char_type; static constexpr auto sendl = std::endl<char_type,std::char_traits<char_type>>; static constexpr auto sflush = std::flush<char_type,std::char_traits<char_type>>; protected: using sfunc_type = std::remove_const_t<decltype(output_adaptor::sendl)>; public: using separator_type = std::variant<std::string,sfunc_type>; destination_type *out; separator_type endline; separator_type separator; protected: void put_separator() noexcept(NO_EXCEPT) { if(this->separator.index() == 0) *this->out << std::get<std::string>(this->separator); if(this->separator.index() == 1) *this->out << std::get<sfunc_type>(this->separator); } void put_endline() noexcept(NO_EXCEPT) { if(this->endline.index() == 0) *this->out << std::get<std::string>(this->endline); if(this->endline.index() == 1) *this->out << std::get<sfunc_type>(this->endline); } public: template<class Terminator = std::string, class Separator = std::string> output_adaptor(destination_type *des = &std::cout, Terminator endl = "\n", Separator sep = " ") noexcept(NO_EXCEPT) : out(des), endline(endl), separator(sep) { *this << std::fixed << std::setprecision(20); } inline auto& seekp(const typename destination_type::off_type off, const std::ios_base::seekdir dir = std::ios_base::cur) noexcept(NO_EXCEPT) { this->out->seekp(off, dir); return *this; }; template<class T> inline output_adaptor& operator<<(T&& s) noexcept(NO_EXCEPT){ this->put(std::forward<T>(s)); return *this; } template<class T = std::string> inline auto& operator()(T&& val = "") noexcept(NO_EXCEPT){ *this << std::forward<T>(val), this->put_endline(); return *this; } template<class T, class ...Args> inline auto& operator()(T&& head, Args&& ...tail) noexcept(NO_EXCEPT){ *this << std::forward<T>(head), this->put_separator(); (*this)(std::forward<Args>(tail)...); return *this; } template<std::forward_iterator I, std::sentinel_for<I> S> inline auto& operator()(I first, S last, const bool terminate = true) noexcept(NO_EXCEPT) { for(I itr=first; itr!=last;) { *this << *itr; if(++itr == last) { if(terminate) this->put_endline(); } else this->put_separator(); } return *this; } template<class T> inline auto& operator()(const std::initializer_list<T> vals) noexcept(NO_EXCEPT) { std::vector wrapped(vals.begin(), vals.end()); (*this)(wrapped.begin(), wrapped.end()); return *this; } template<class T0, class T1> inline auto& conditional(const bool cond, const T0& a, const T1& b) noexcept(NO_EXCEPT) { if(cond) (*this)(a); else (*this)(b); return *this; } inline auto& yesno(const bool cond) noexcept(NO_EXCEPT) { if(cond) this->yes(); else this->no(); return *this; } inline auto yes() noexcept(NO_EXCEPT) { *this->out << "Yes"; this->put_endline(); return *this; } inline auto no() noexcept(NO_EXCEPT) { *this->out << "No"; this->put_endline(); return *this; } inline auto flush() noexcept(NO_EXCEPT) { *this->out << std::flush; return *this; } }; } // namespace uni #line 7 "adaptor/io.hpp" namespace uni { uni::input_adaptor _input; uni::output_adaptor _print; } #define input uni::_input #define print uni::_print #line 2 "adaptor/multi_container.hpp" #line 7 "adaptor/multi_container.hpp" #line 9 "adaptor/multi_container.hpp" #line 12 "adaptor/multi_container.hpp" #line 15 "adaptor/multi_container.hpp" #line 18 "adaptor/multi_container.hpp" namespace uni { namespace internal { namespace multi_container_impl { template<class Holder> struct base : Holder { using Holder::Holder; protected: template<std::integral T> constexpr auto _positivize_index(const T _x) const noexcept(NO_EXCEPT) { auto x = static_cast<internal::size_t>(_x); return x < 0 ? this->size() + x : x; } }; } // namespace multi_contatiner_impl } // namespace internal template<class T, unsigned int RANK, template<class...> class Holder = vector, template<class...> class Container = vector> struct multi_container : internal::multi_container_impl::base<Holder<multi_container<T, RANK - 1, Holder, Container>>> { private: using base = internal::multi_container_impl::base<Holder<multi_container<T, RANK - 1, Holder, Container>>>; public: using base::base; template<std::integral Head, class... Tail> constexpr multi_container(const Head head, Tail&&... tail) noexcept(NO_EXCEPT) : base(head, multi_container<T, RANK - 1, Holder, Container>(std::forward<Tail>(tail)...)) { assert(head >= 0); } template<std::integral Head, class... Tail> constexpr T& operator()(Head _head, Tail&&... tail) noexcept(NO_EXCEPT) { static_assert(std::is_integral_v<Head>, "index must be integral"); const auto index = this->_positivize_index(_head); assert(0 <= index && index < std::ranges::ssize(*this)); return (*this)[index](std::forward<Tail>(tail)...); } template<std::integral Head, class... Tail> constexpr T& operator()(Head _head, Tail&&... tail) const noexcept(NO_EXCEPT) { static_assert(std::is_integral_v<Head>, "index must be integral"); const auto index = this->_positivize_index(_head); assert(0 <= index && index < std::ranges::ssize(*this)); return (*this)[index](std::forward<Tail>(tail)...); } }; template<class T, template<class...> class Holder, template<class...> class Container> struct multi_container<T, 1, Holder, Container> : internal::multi_container_impl::base<Container<T>> { using internal::multi_container_impl::base<Container<T>>::base; template<class... Args> constexpr multi_container(const Args&... args) noexcept(NO_EXCEPT) : internal::multi_container_impl::base<Container<T>>(args...) {} template<class Index> constexpr T& operator()(Index&& _index) noexcept(NO_EXCEPT) { const auto index = this->_positivize_index(std::forward<T>(_index)); assert(0 <= index && index < std::ranges::ssize(*this)); return (*this)[index]; } template<class Index> constexpr T& operator()(Index&& _index) const noexcept(NO_EXCEPT) { const auto index = this->_positivize_index(std::forward<T>(_index)); assert(0 <= index && index < std::ranges::ssize(*this)); return (*this)[index]; } }; template<class T, template<class...> class Holder, template<class...> class Container> struct multi_container<T, 0, Holder, Container> { static_assert(internal::EXCEPTION_ON_TYPE<T>, "invalid rank: 0, should be 1 or more"); }; } // namespace uni #line 2 "adaptor/queue_by_stack.hpp" #line 6 "adaptor/queue_by_stack.hpp" #line 9 "adaptor/queue_by_stack.hpp" namespace uni { template<class In, class Out = In> struct queue_by_stack { static_assert(std::same_as<typename In::value_type, typename Out::value_type>); static_assert(std::common_reference_with<typename In::size_type, typename Out::size_type>); using value_type = In::value_type; using size_type = std::common_type_t<typename In::size_type, typename Out::size_type>; protected: In _in; Out _out; private: inline void _shift() noexcept(NO_EXCEPT) { if(!this->_out.empty()) return; while(!this->_in.empty()) { this->_out.push(this->_in.top()); this->_in.pop(); } } public: queue_by_stack() noexcept = default; inline bool empty() const noexcept(NO_EXCEPT) { return this->_in.empty() && this->_out.empty(); } inline auto size() const noexcept(NO_EXCEPT) { return this->_in.size() + this->_out.size(); } inline decltype(auto) front() noexcept(NO_EXCEPT) { this->_shift(); assert(!this->_out.empty()); return this->_out.top(); } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline decltype(auto) front_or(T&& val) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(val)); else return this->front(); } inline auto& clear() noexcept(NO_EXCEPT) { this->_in.clear(), this->_out.clear(); return *this; } template<std::convertible_to<value_type> T = value_type> inline auto& push(T&& val) noexcept(NO_EXCEPT) { this->_in.push(std::forward<T>(val)); return *this; } template<class... Args> inline decltype(auto) emplace(Args&&... args) noexcept(NO_EXCEPT) { return this->_in.emplace(std::forward<Args>(args)...); } auto& pop() noexcept(NO_EXCEPT) { this->_shift(); assert(!this->_out.empty()); this->_out.pop(); return *this; } }; } // namespace uni #line 2 "adaptor/range_extractor.hpp" #line 7 "adaptor/range_extractor.hpp" #line 10 "adaptor/range_extractor.hpp" namespace uni { template<class Container> struct range_extractor : Container { using size_type = typename Container::size_type; using value_type = typename Container::value_type; protected: using default_func_noarg_type = std::function<value_type(void)>; using default_func_type = std::function<value_type(size_type)>; size_type _begin = 0; size_type _end; int _default_type = 0; value_type _default_val = value_type(); default_func_noarg_type _default_func_noarg; default_func_type _default_func; inline static value_type _tmp; inline value_type _get_default(const size_type key) const noexcept(NO_EXCEPT) { if(this->_default_type == 0) return this->_default_val; if(this->_default_type == 1) return this->_default_func_noarg(); if(this->_default_type == 2) return this->_default_func(key); else assert(false); } public: template<class... Args> explicit range_extractor(Args&&... args) noexcept(NO_EXCEPT) : Container(std::forward<Args>(args)...) { this->_begin = 0; this->_end = this->size(); } inline auto& extract(const size_type begin, const size_type end) noexcept(NO_EXCEPT) { assert(begin <= end); this->_begin = begin, this->_end = end; return *this; } inline auto& set_default(const value_type& val) noexcept(NO_EXCEPT) { this->_default_val = val; this->_default_type = 0; return *this; } inline auto& set_default(const default_func_noarg_type func) noexcept(NO_EXCEPT) { this->_default_func_noarg = func; this->_default_type = 1; return *this; } inline auto& set_default(const default_func_type func) noexcept(NO_EXCEPT) { this->_default_func = func; this->_default_type = 2; return *this; } inline auto& operator[](const size_type pos) noexcept(NO_EXCEPT) { if(pos < this->_begin or this->_end <= pos) return range_extractor::_tmp = this->_get_default(pos); return this->Container::operator[](pos); } inline const auto& operator[](const size_type pos) const noexcept(NO_EXCEPT) { if(pos < this->_begin or this->_end <= pos) return range_extractor::_tmp = this->_get_default(pos); return this->Container::operator[](pos); } inline auto& operator()(const size_type pos) noexcept(NO_EXCEPT) { return this->Container::operator[](pos); } inline const auto& operator()(const size_type pos) const noexcept(NO_EXCEPT) { return this->Container::operator[](pos); } inline std::optional<value_type> get(const size_type pos) const noexcept(NO_EXCEPT) { if(pos < this->_begin or this->_end <= pos) return {}; return this->Container::operator[](pos); } }; } #line 2 "adaptor/stack.hpp" #line 6 "adaptor/stack.hpp" namespace uni { template<class T, class Allocator = std::allocator<T>> using stack = std::stack<T, std::vector<T, Allocator>>; } // namespace uni #line 2 "adaptor/virtual_map.hpp" #line 5 "adaptor/virtual_map.hpp" #line 7 "adaptor/virtual_map.hpp" namespace uni { template<class> struct virtual_combined_map {}; template<class Mapped, class... Keys> struct virtual_combined_map<Mapped(Keys...)> { using key_type = std::tuple<Keys...>; using mapped_type = Mapped; using value_type = std::pair<key_type,mapped_type>; protected: std::function<Mapped(Keys...)> _f; public: virtual_combined_map() = default; template<class F> explicit virtual_combined_map(F&& f) noexcept(NO_EXCEPT) : _f(f) {}; inline const auto* get_functor() const noexcept(NO_EXCEPT) { return this->_f; } inline auto* get_functor() noexcept(NO_EXCEPT) { return this->_f; } template<class F> inline auto& set_functor(F&& f) const noexcept(NO_EXCEPT) { return this->_f = f; } inline mapped_type operator()(const Keys&... key) const noexcept(NO_EXCEPT) { return this->_f(key...); } inline mapped_type operator[](const key_type& key) const noexcept(NO_EXCEPT) { return std::apply(this->_f, key); } }; template<class Key, class Mapped> struct virtual_map : virtual_combined_map<Mapped(Key)> { using key_type = Key; using mapped_type = Mapped; using value_type = std::pair<key_type,mapped_type>; using virtual_combined_map<mapped_type(key_type)>::virtual_combined_map; inline mapped_type operator[](const key_type& key) const noexcept(NO_EXCEPT) { return this->_f(key); } }; }; // namesapce uni #line 2 "include/algebraic.hpp" #line 2 "algebraic/bit_and.hpp" #line 6 "algebraic/bit_and.hpp" namespace uni { namespace algebraic { template<class T> struct bit_and : base<T>, associative, scalar_multipliable<bit_and<T>>::identity, commutative { using base<T>::base; bit_and() noexcept(NO_EXCEPT) : base<T>(uni::numeric_limits<T>::max()) {}; friend inline bit_and operator+(const bit_and& lhs, const bit_and& rhs) noexcept(NO_EXCEPT) { return lhs.val() bitand rhs.val(); } }; } // namespace algebraic } // namespace uni #line 2 "algebraic/bit_or.hpp" #line 5 "algebraic/bit_or.hpp" namespace uni { namespace algebraic { template<class T> struct bit_or : base<T>, scalar_multipliable<bit_or<T>>::identity, associative, commutative { using base<T>::base; friend inline bit_or operator+(const bit_or& lhs, const bit_or& rhs) noexcept(NO_EXCEPT) { return lhs.val() bitor rhs.val(); } }; } // namespace algebraic } // namespace uni #line 2 "algebraic/combined.hpp" #line 6 "algebraic/combined.hpp" #line 9 "algebraic/combined.hpp" #line 12 "algebraic/combined.hpp" namespace uni { namespace algebraic { template< internal::magma M0, internal::magma M1 > struct combined : base<std::pair<M0, M1>>, std::conditional_t<internal::associative<M0> && internal::associative<M1>, associative, uni::internal::dummy>, std::conditional_t<internal::commutative<M0> && internal::commutative<M1>, commutative, uni::internal::dummy> { using base<std::pair<M0, M1>>::base; template<class T> requires std::convertible_to<T, M0> && std::convertible_to<T, M1> combined(const T& v) : combined(v, v) {}; friend inline combined operator+(const combined& lhs, const combined& rhs) noexcept(NO_EXCEPT) { return { lhs->first + rhs->first, lhs->second + rhs->second }; } template<std::integral Scalar> friend inline combined&& operator*(const Scalar k, const combined& val) noexcept(NO_EXCEPT) { return { k * val->first, k * val->second }; } friend inline combined operator-(const combined& val) noexcept(NO_EXCEPT) requires internal::invertible<M0> && internal::invertible<M1> { return { -val->first, -val->second }; } }; } // namespace algebraic } // namespace uni #line 2 "algebraic/opposite.hpp" #line 6 "algebraic/opposite.hpp" #line 9 "algebraic/opposite.hpp" #line 12 "algebraic/opposite.hpp" namespace uni { namespace algebraic { template<internal::magma M> struct opposite : std::conditional_t<internal::associative<M>, associative, uni::internal::dummy>, std::conditional_t<internal::commutative<M>, commutative, uni::internal::dummy> { using value_type = M::value_type; private: M _value; public: template<std::convertible_to<M> T> opposite(const T& v) : _value(v) {}; template<class... Args> requires std::constructible_from<value_type, Args...> opposite(Args&&... args) noexcept(NO_EXCEPT) : _value(std::forward<Args>(args)...) {} inline explicit operator value_type() const noexcept(NO_EXCEPT) { return this->_value.val(); } inline auto val() const noexcept(NO_EXCEPT) { return this->_value.val(); }; inline const value_type* operator->() const noexcept(NO_EXCEPT) { return this->_value.operator->(); }; inline value_type* operator->() noexcept(NO_EXCEPT) { return this->_value.operator->(); }; friend inline auto operator<=>(const opposite& lhs, const opposite& rhs) noexcept(NO_EXCEPT) { return lhs._value <=> rhs._value; }; friend inline bool operator==(const opposite& lhs, const opposite& rhs) noexcept(NO_EXCEPT) { return lhs._value == rhs._value; } friend inline opposite operator+(const opposite& lhs, const opposite& rhs) noexcept(NO_EXCEPT) { return rhs._value + lhs._value; } friend inline opposite operator-(const opposite& val) noexcept(NO_EXCEPT) requires internal::invertible<M> { return -val._value; } }; template<internal::magma M> struct make_opposite; template<internal::magma M> struct make_opposite<opposite<M>> { using type = M; }; template<internal::magma M> requires internal::commutative<M> struct make_opposite<M> { using type = M; }; template<internal::magma M> requires (!internal::commutative<M>) struct make_opposite<M> { using type = opposite<M>; }; template<internal::magma M> using make_opposite_t = make_opposite<M>::type; } // namespace algebraic } // namespace uni #line 2 "include/convolutions.hpp" #line 2 "convolution/gcd.hpp" #line 6 "convolution/gcd.hpp" #line 9 "convolution/gcd.hpp" #line 2 "numeric/divisor_multiple_transform.hpp" #line 5 "numeric/divisor_multiple_transform.hpp" #line 2 "numeric/prime_enumerator.hpp" #line 10 "numeric/prime_enumerator.hpp" #line 13 "numeric/prime_enumerator.hpp" #line 15 "numeric/prime_enumerator.hpp" #line 18 "numeric/prime_enumerator.hpp" #line 22 "numeric/prime_enumerator.hpp" namespace uni { // Thanks to: https://qiita.com/peria/items/e0ab38f95d16a5f7cc58 template<class T> struct prime_enumerator : std::ranges::view_interface<prime_enumerator<T>> { using value_type = T; using size_type = internal::size_t; protected: using impl_type = std::uint32_t; impl_type _n = 0; using small_bit_type = std::uint8_t; using large_bit_type = std::uint64_t; static constexpr impl_type SEGMENT_SIZE = 1'000'000; static constexpr impl_type MOD30[8] = { 1, 7, 11, 13, 17, 19, 23, 29 }; static constexpr small_bit_type MASK[8][8] = { { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }, { 0xfd, 0xdf, 0xef, 0xfe, 0x7f, 0xf7, 0xfb, 0xbf }, { 0xfb, 0xef, 0xfe, 0xbf, 0xfd, 0x7f, 0xf7, 0xdf }, { 0xf7, 0xfe, 0xbf, 0xdf, 0xfb, 0xfd, 0x7f, 0xef }, { 0xef, 0x7f, 0xfd, 0xfb, 0xdf, 0xbf, 0xfe, 0xf7 }, { 0xdf, 0xf7, 0x7f, 0xfd, 0xbf, 0xfe, 0xef, 0xfb }, { 0xbf, 0xfb, 0xf7, 0x7f, 0xfe, 0xef, 0xdf, 0xfd }, { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }, }; static constexpr impl_type C1[8] = { 6, 4, 2, 4, 2, 4, 6, 2 }; static constexpr impl_type C0[8][8] = { { 0, 0, 0, 0, 0, 0, 0, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1 }, { 2, 2, 0, 2, 0, 2, 2, 1 }, { 3, 1, 1, 2, 1, 1, 3, 1 }, { 3, 3, 1, 2, 1, 3, 3, 1 }, { 4, 2, 2, 2, 2, 2, 4, 1 }, { 5, 3, 1, 4, 1, 3, 5, 1 }, { 6, 4, 2, 4, 2, 4, 6, 1 }, }; size_type _size; impl_type _sqrt_n = 0, _sqrt_ni = 0, _quart_n = 0; std::valarray<small_bit_type> _small; std::valarray<large_bit_type> _large; std::vector<impl_type> _indecies; small_bit_type* _flag = nullptr; inline void _init(const value_type n, const impl_type size) noexcept(NO_EXCEPT) { const size_type blocks = (size + 7) >> 3; this->_large.resize(blocks + 1, ~0UL); this->_flag = reinterpret_cast<small_bit_type*>(&(this->_large[0])); this->_flag[0] = 0xfe; value_type r = n % 30; if(r <= 1) this->_flag[size - 1] = 0x0; else if(r <= 7) this->_flag[size - 1] = 0x1; else if(r <= 11) this->_flag[size - 1] = 0x3; else if(r <= 13) this->_flag[size - 1] = 0x7; else if(r <= 17) this->_flag[size - 1] = 0xf; else if(r <= 19) this->_flag[size - 1] = 0x1f; else if(r <= 23) this->_flag[size - 1] = 0x3f; else if(r <= 29) this->_flag[size - 1] = 0x7f; if(n < 30) this->_flag[0] &= 0xfe; this->_large[blocks - 1] <<= 64 - ((size & 7) << 3); this->_large[blocks - 1] >>= 64 - ((size & 7) << 3); this->_large[blocks] = 0; // for(auto x : this->_large) debug(std::bitset<64>(x)); } inline void _gen_small() noexcept(NO_EXCEPT) { const impl_type quart_ni = this->_quart_n / 30 + 1; this->_small.resize(this->_sqrt_ni, 0xff); this->_small[0] = 0xfe; REP(i, quart_ni) { for(small_bit_type flags = this->_small[i]; flags; flags &= flags - 1) { const int ibit = lowest_bit_pos(flags); const impl_type m = prime_enumerator::MOD30[ibit]; const impl_type pm = 30 * i + 2 * m; for( impl_type j = i * pm + (m * m) / 30, k = ibit; j < this->_sqrt_ni; j += i * prime_enumerator::C1[k] + prime_enumerator::C0[ibit][k], k = (k + 1) & 7 ) { this->_small[j] &= prime_enumerator::MASK[ibit][k]; } } } REP(i, this->_sqrt_ni) { for(small_bit_type flags = this->_small[i]; flags; flags &= flags - 1) { const int ibit = lowest_bit_pos(flags); const impl_type m = prime_enumerator::MOD30[ibit]; impl_type j = i * (30 * i + 2 * m) + (m * m) / 30; this->_indecies.emplace_back(((j + prime_enumerator::SEGMENT_SIZE) << 3) | ibit); } } } inline void _gen_core(small_bit_type *const flags, const impl_type size) noexcept(NO_EXCEPT) { auto p_index = this->_indecies.begin(); REP(i, this->_sqrt_ni) { for(small_bit_type primes = this->_small[i]; primes; primes &= primes - 1) { const int ibit = lowest_bit_pos(primes); impl_type j = (*p_index >> 3) - prime_enumerator::SEGMENT_SIZE; impl_type k = *p_index & 7; for(; j < size; j += i * prime_enumerator::C1[k] + prime_enumerator::C0[ibit][k], k = (k + 1) & 7) { flags[j] &= prime_enumerator::MASK[ibit][k]; } *p_index = ((j << 3) | k); ++p_index; } } } using iterator_interface = internal::bidirectional_iterator_interface<const value_type>; public: struct iterator; using const_iterator = iterator; prime_enumerator() noexcept {}; prime_enumerator(const value_type n) noexcept(NO_EXCEPT) : _n(n) { assert(n >= 0); assert(std::endian::native == std::endian::little); this->_sqrt_n = static_cast<impl_type>(sqrt_ceil(this->_n + 1)); this->_sqrt_ni = this->_sqrt_n / 30 + 1; this->_quart_n = static_cast<impl_type>(sqrt_ceil(this->_sqrt_n)); this->_gen_small(); impl_type size = (this->_n + 1) / 30 + 1; this->_init(this->_n + 1, size); for(small_bit_type* seg = this->_flag; ; seg += prime_enumerator::SEGMENT_SIZE) { if(size < prime_enumerator::SEGMENT_SIZE) { this->_gen_core(seg, size); break; }; this->_gen_core(seg, prime_enumerator::SEGMENT_SIZE); size -= prime_enumerator::SEGMENT_SIZE; } this->_size = (this->_n >= 2) + (this->_n >= 3) + (this->_n >= 5); for(const large_bit_type f : this->_large) this->_size += std::popcount(f); } inline size_type size() const noexcept(NO_EXCEPT) { return this->_size; } inline size_type count(const T x) const noexcept(NO_EXCEPT) { assert(0 <= x and x <= this->_n); size_type res = (x >= 2) + (x >= 3) + (x >= 5); T count = 0; constexpr int large_bit_width = std::numeric_limits<large_bit_type>::digits; constexpr int large_bit_size = (30 * large_bit_width) >> 3; for(const large_bit_type f : this->_large) { if(count + large_bit_size > x) { REP(i, large_bit_width) { if(count + prime_enumerator::MOD30[i & 7] > x) break; if((f >> i) & 1) res++; if(((i + 1) & 7) == 0) count += 30; } break; } res += std::popcount(f); count += large_bit_size; } return res; } inline size_type count(const T l, const T r) const noexcept(NO_EXCEPT) { assert(l <= r); return this->count(r) - this->count(l - 1); } inline bool is_prime(const T v) const noexcept(NO_EXCEPT) { assert(0 <= v and v <= this->_n); if(v == 0 or v == 1) return false; if(v == 2 or v == 3 or v == 5) return true; if((v & 1) == 0 or v % 3 == 0 or v % 5 == 0) return false; REP(i, 8) { if(prime_enumerator::MOD30[i] == v % 30) { return static_cast<bool>((this->_flag[v / 30] >> i) & 1); } } assert(false); } inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, -1); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } struct iterator : iterator_interface { protected: value_type _n = 0; size_type _index = 0; const std::valarray<large_bit_type>* _flags = nullptr; size_type _block = -1, _flag_size; int _bit = 0; inline value_type _value() const noexcept(NO_EXCEPT) { if(this->_bit < 0) return numeric_limits<value_type>::arithmetic_infinity(); if(this->_block < 0) { if(this->_bit == 0) return 2; if(this->_bit == 1) return 3; if(this->_bit == 2) return 5; } return ( value_type{30} * ((this->_block << 3) + (this->_bit >> 3)) + prime_enumerator::MOD30[this->_bit & 7] ); } public: iterator() noexcept = default; iterator(const prime_enumerator *const super, const int bit) noexcept(NO_EXCEPT) : _n(super->_n), _flags(&super->_large), _flag_size(static_cast<size_type>(super->_large.size())), _bit(bit) { if(bit < 0) { this->_index = super->size(); this->_block = static_cast<size_type>(super->_large.size()) - 1; } } inline size_type index() const noexcept(NO_EXCEPT) { return this->_index; } inline value_type operator*() const noexcept(NO_EXCEPT) { const value_type res = this->_value(); return (res > this->_n ? -1 : res); } inline iterator& operator++() noexcept(NO_EXCEPT) { if(this->_value() > this->_n) return *this; ++this->_index; if(this->_block < 0) { ++this->_bit; if(this->_bit > 2) this->_block = 0, this->_bit = 1; return *this; } int next; while(true) { const large_bit_type mask = this->_bit >= 63 ? 0UL : ~((1UL << (this->_bit + 1)) - 1); next = lowest_bit_pos(this->_flags->operator[](this->_block) & mask); if(next >= 0) break; this->_block++; this->_bit = -1; if(this->_block >= this->_flag_size) break; } this->_bit = next; return *this; } inline iterator& operator--() noexcept(NO_EXCEPT) { if(this->_block < 0) { if(this->_bit > 0) --this->_bit, --this->_index; return *this; } --this->_index; int prev = -1; while(true) { if(0 < this->_bit) { const large_bit_type mask = this->_bit >= 64 ? ~0UL : ((1UL << this->_bit) - 1); prev = highest_bit_pos(this->_flags->operator[](this->_block) & mask); } if(prev >= 0) break; --this->_block; this->_bit = 64; if(this->_block < 0) { this->_bit = (this->_n >= 3) + (this->_n >= 5); return *this; } } this->_bit = prev; return *this; } inline iterator operator++(int) noexcept(NO_EXCEPT) { const auto res = *this; ++(*this); return res; } inline iterator operator--(int) noexcept(NO_EXCEPT) { const auto res = *this; --(*this); return res; } friend inline bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) { return lhs._index == rhs._index; } friend inline auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) { return lhs._index <=> rhs._index; } friend inline auto operator-(const iterator& lhs, const iterator& rhs) { return lhs._index - rhs._index; } }; }; } // namespace uni namespace std::ranges { template<class T> inline constexpr bool enable_borrowed_range<uni::prime_enumerator<T>> = true; } // namespace std::ranges #line 10 "numeric/divisor_multiple_transform.hpp" // Thanks to: https://nyaannyaan.github.io/library/multiplicative-function/divisor-multiple-transform.hpp.html namespace uni { namespace divisor_transform { using size_type = internal::size_t; template<std::size_t OFFSET, std::ranges::sized_range R> requires (!requires { typename R::mapped_type; }) auto zeta(R&& range) noexcept(NO_EXCEPT) { const auto n = std::ranges::ssize(range) + OFFSET - 1; ITR(p, uni::prime_enumerator(n)) { for(size_type k=1; k*p <= n; ++k) range[k*p - OFFSET] += range[k - OFFSET]; } } template<std::size_t OFFSET, std::ranges::sized_range R> requires (!requires { typename R::mapped_type; }) auto mobius(R&& range) noexcept(NO_EXCEPT) { const auto n = std::ranges::ssize(range) + OFFSET - 1; ITR(p, uni::prime_enumerator(n)) { for(size_type k=n/p; k>0; --k) range[k*p - OFFSET] -= range[k - OFFSET]; } } template<std::ranges::sized_range R> auto zeta(R&& range) noexcept(NO_EXCEPT) { return zeta<0>(range); } template<std::ranges::sized_range R> auto mobius(R&& range) noexcept(NO_EXCEPT) { return mobius<0>(range); } template<std::ranges::input_range R> requires requires { typename R::mapped_type; } auto zeta(R&& range) noexcept(NO_EXCEPT) { auto begin = std::ranges::begin(range); auto end = std::ranges::end(range); for(auto itr1 = end; itr1-- != begin; ) { for(auto itr2 = begin; itr2 != end; ++itr2) { if(itr1->first == itr2->first) break; if(itr1->first % itr2->first == 0) itr1->second += itr2->second; } } } template<std::ranges::input_range R> requires requires { typename R::mapped_type; } auto mobius(R&& range) noexcept(NO_EXCEPT) { auto begin = std::ranges::begin(range); auto end = std::ranges::end(range); for(auto itr2 = begin; itr2 != end; ++itr2) { for(auto itr1 = end; (itr1--) != begin; ) { if(itr1->first == itr2->first) break; if(itr1->first % itr2->first == 0) itr1->second -= itr2->second; } } } } // namespace divisor_transform namespace multiple_transform { using size_type = internal::size_t; template<std::size_t OFFSET, std::ranges::sized_range R> requires (!requires { typename R::mapped_type; }) auto zeta(R&& range) noexcept(NO_EXCEPT) { const auto n = std::ranges::ssize(range) + OFFSET - 1; ITR(p, uni::prime_enumerator(n)) { for(size_type k=n/p; k>0; --k) range[k - OFFSET] += range[k*p - OFFSET]; } } template<std::size_t OFFSET, std::ranges::sized_range R> requires (!requires { typename R::mapped_type; }) auto mobius(R&& range) noexcept(NO_EXCEPT) { const auto n = std::ranges::ssize(range) + OFFSET - 1; ITR(p, uni::prime_enumerator(n)) { for(size_type k=1; k*p <= n; ++k) range[k - OFFSET] -= range[k*p - OFFSET]; } } template<std::ranges::sized_range R> auto zeta(R&& range) noexcept(NO_EXCEPT) { return zeta<0>(range); } template<std::ranges::sized_range R> auto mobius(R&& range) noexcept(NO_EXCEPT) { return mobius<0>(range); } template<std::ranges::input_range R> requires requires { typename R::mapped_type; } auto zeta(R&& range) noexcept(NO_EXCEPT) { auto begin = std::ranges::begin(range); auto end = std::ranges::end(range); for(auto itr2 = begin; itr2 != end; ++itr2) { for(auto itr1 = end; --itr1 != itr2; ) { if(itr1->first % itr2->first == 0) itr2->second += itr1->second; } } } template<std::ranges::input_range R> requires requires { typename R::mapped_type; } auto mobius(R&& range) noexcept(NO_EXCEPT) { auto begin = std::ranges::begin(range); auto end = std::ranges::end(range); for(auto itr2 = end; itr2-- != begin; ) { for(auto itr1 = end; --itr1 != itr2; ) { if(itr1->first % itr2->first == 0) itr2->second -= itr1->second; } } } } // namespace multiple_transform } // namespace uni #line 11 "convolution/gcd.hpp" #line 13 "convolution/gcd.hpp" namespace uni { template<std::ranges::range Res, std::size_t OFFSET, std::ranges::sized_range R0, std::ranges::sized_range R1> Res gcd_convolution(R0 v0, R1 v1) { assert(std::ranges::size(v0) == std::ranges::size(v1)); multiple_transform::zeta<OFFSET>(v0), multiple_transform::zeta<OFFSET>(v1); REP(i, std::ranges::size(v0)) v0[i] *= v1[i]; multiple_transform::mobius<OFFSET>(v0); if constexpr(std::convertible_to<R0, Res>) return v0; else return Res(ALL(v0)); } template<std::size_t OFFSET, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> auto gcd_convolution(R0&& v0, R1&& v1) { using common_type = std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>; return gcd_convolution<valarray<common_type>, OFFSET>(v0, v1); } template<std::ranges::range Res, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> auto gcd_convolution(R0&& v0, R1&& v1) { return gcd_convolution<Res, 0>(v0, v1); } template<std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> auto gcd_convolution(R0&& v0, R1&& v1) { return gcd_convolution<0>(v0, v1); } } // namespace uni #line 2 "convolution/lcm.hpp" #line 6 "convolution/lcm.hpp" #line 9 "convolution/lcm.hpp" #line 11 "convolution/lcm.hpp" #line 13 "convolution/lcm.hpp" namespace uni { template<std::ranges::range Res, std::size_t OFFSET, std::ranges::sized_range R0, std::ranges::sized_range R1> Res lcm_convolution(R0 v0, R1 v1) { assert(std::ranges::size(v0) == std::ranges::size(v1)); divisor_transform::zeta<OFFSET>(v0), divisor_transform::zeta<OFFSET>(v1); REP(i, std::ranges::size(v0)) v0[i] *= v1[i]; divisor_transform::mobius<OFFSET>(v0); if constexpr(std::convertible_to<R0, Res>) return v0; else return Res(ALL(v0)); } template<std::size_t OFFSET, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> auto lcm_convolution(R0&& v0, R1&& v1) { using common_type = std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>; return lcm_convolution<valarray<common_type>, OFFSET>(v0, v1); } template<std::ranges::range Res, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> auto lcm_convolution(R0&& v0, R1&& v1) { return lcm_convolution<Res, 0>(v0, v1); } template<std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> auto lcm_convolution(R0&& v0, R1&& v1) { return lcm_convolution<0>(v0, v1); } } // namespace uni #line 2 "convolution/sum.hpp" #line 7 "convolution/sum.hpp" #line 2 "convolution/internal/butterfly.hpp" #line 13 "convolution/internal/butterfly.hpp" #line 16 "convolution/internal/butterfly.hpp" #line 19 "convolution/internal/butterfly.hpp" #line 21 "convolution/internal/butterfly.hpp" #line 23 "convolution/internal/butterfly.hpp" namespace uni { namespace internal { // Thanks to: atocder/convolution template<uni::internal::modint_family mint> struct fft_info { static constexpr mint g = primitive_root<mint>(mint::mod()); static constexpr auto rank2 = std::countr_zero(mint::mod() - 1); std::array<mint, rank2 + 1> root; std::array<mint, rank2 + 1> iroot; std::array<mint, std::max(0, rank2 - 2 + 1)> rate2; std::array<mint, std::max(0, rank2 - 2 + 1)> irate2; std::array<mint, std::max(0, rank2 - 3 + 1)> rate3; std::array<mint, std::max(0, rank2 - 3 + 1)> irate3; consteval fft_info() { this->root[rank2] = g.pow((mint::mod() - 1) >> this->rank2); this->iroot[rank2] = this->root[this->rank2].inv(); REPD(i, rank2) { this->root[i] = this->root[i + 1] * this->root[i + 1]; this->iroot[i] = this->iroot[i + 1] * this->iroot[i + 1]; } { mint prod = mint::one, iprod = mint::one; REP(i, rank2 - 1) { this->rate2[i] = this->root[i + 2] * prod; this->irate2[i] = this->iroot[i + 2] * iprod; prod *= this->iroot[i + 2]; iprod *= this->root[i + 2]; } } { mint prod = mint::one, iprod = mint::one; REP(i, rank2 - 2) { this->rate3[i] = this->root[i + 3] * prod; this->irate3[i] = this->iroot[i + 3] * iprod; prod *= this->iroot[i + 3]; iprod *= this->root[i + 3]; } } } }; } // namespace internal template<std::ranges::sized_range R> requires internal::static_modint_family<std::ranges::range_value_t<R>> void butterfly(R& v1) { using mint = std::ranges::range_value_t<R>; const auto n = std::ranges::ssize(v1); const auto h = to_signed(std::countr_zero(to_unsigned(n))); static constexpr internal::fft_info<mint> info; internal::size_t len = 0; while(len < h) { if(h - len == 1) { const internal::size_t p = 1 << (h - len - 1); mint rot = mint::one; REP(s, 1 << len) { const internal::size_t offset = s << (h - len); REP(i, p) { const auto l = v1[i + offset]; const auto r = v1[i + offset + p] * rot; v1[i + offset] = l + r; v1[i + offset + p] = l - r; } if(s + 1 != (1 << len)) { rot *= info.rate2[std::countr_zero(~to_unsigned(s))]; } } ++len; } else { const internal::size_t p = 1 << (h - len - 2); const mint imag = info.root[2]; mint rot = mint::one; REP(s, 1 << len) { const mint rot2 = rot * rot; const mint rot3 = rot2 * rot; const internal::size_t offset = s << (h - len); REP(i, p) { const auto mod2 = 1ULL * mint::mod() * mint::mod(); const auto a0 = 1ULL * v1[i + offset].val(); const auto a1 = 1ULL * v1[i + offset + p].val() * rot.val(); const auto a2 = 1ULL * v1[i + offset + 2 * p].val() * rot2.val(); const auto a3 = 1ULL * v1[i + offset + 3 * p].val() * rot3.val(); const auto a1na3imag = 1ULL * mint{ a1 + mod2 - a3 }.val() * imag.val(); const auto na2 = mod2 - a2; v1[i + offset] = a0 + a2 + a1 + a3; v1[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3)); v1[i + offset + 2 * p] = a0 + na2 + a1na3imag; v1[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag); } if(s + 1 != (1 << len)) rot *= info.rate3[std::countr_zero(~to_unsigned(s))]; } len += 2; } } } template<std::ranges::sized_range R> requires internal::static_modint_family<std::ranges::range_value_t<R>> void butterfly_inv(R& v1) { using mint = std::ranges::range_value_t<R>; const auto n = std::ranges::ssize(v1); const auto h = std::countr_zero(to_unsigned(n)); static constinit internal::fft_info<mint> info; internal::size_t len = h; while(len > 0) { if(len == 1) { const internal::size_t p = 1 << (h - len); mint irot = mint::one; REP(s, 1 << (len - 1)) { const internal::size_t offset = s << (h - len + 1); REP(i, p) { const auto l = v1[i + offset]; const auto r = v1[i + offset + p]; v1[i + offset] = l + r; v1[i + offset + p] = to_unsigned(mint::mod() + l.val() - r.val()) * irot.val(); } if(s + 1 != (1 << (len - 1))) irot *= info.irate2[std::countr_zero(~to_unsigned(s))]; } --len; } else { const auto p = 1 << (h - len); const mint iimag = info.iroot[2]; mint irot = mint::one; REP(s, 1 << (len - 2)) { const mint irot2 = irot * irot; const mint irot3 = irot2 * irot; const internal::size_t offset = s << (h - len + 2); REP(i, p) { const auto a0 = 1ULL * v1[i + offset + 0 * p].val(); const auto a1 = 1ULL * v1[i + offset + 1 * p].val(); const auto a2 = 1ULL * v1[i + offset + 2 * p].val(); const auto a3 = 1ULL * v1[i + offset + 3 * p].val(); const auto a2na3iimag = 1ULL * mint{ (mint::mod() + a2 - a3) * iimag.val() }.val(); v1[i + offset] = a0 + a1 + a2 + a3; v1[i + offset + 1 * p] = (a0 + (mint::mod() - a1) + a2na3iimag) * irot.val(); v1[i + offset + 2 * p] = (a0 + a1 + (mint::mod() - a2) + (mint::mod() - a3)) * irot2.val(); v1[i + offset + 3 * p] = (a0 + (mint::mod() - a1) + (mint::mod() - a2na3iimag)) * irot3.val(); } if(s + 1 != (1 << (len - 2))) irot *= info.irate3[std::countr_zero(~to_unsigned(s))]; } len -= 2; } } } template<class Res, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::same_as<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> && internal::static_modint_family<std::ranges::range_value_t<R0>> Res convolution_naive(R0&& v0, R1&& v1) { const auto n = std::ranges::ssize(v0); const auto m = std::ranges::ssize(v1); Res ans(n + m - 1); if(n < m) { REP(j, m) REP(i, n) ans[i + j] += v0[i] * v1[j]; } else { REP(i, n) REP(j, m) ans[i + j] += v0[i] * v1[j]; } return ans; } template<class Res, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::same_as<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> && internal::static_modint_family<std::ranges::range_value_t<R0>> && internal::resizable_range<R0> && internal::resizable_range<R1> && std::convertible_to<std::ranges::range_value_t<R0>, std::ranges::range_value_t<Res>> Res convolution_fft(R0 v0, R1 v1) { using mint = std::ranges::range_value_t<R0>; const auto n = std::ranges::ssize(v0); const auto m = std::ranges::ssize(v1); const auto z = to_signed(std::bit_ceil(to_unsigned(n + m - 1))); v0.resize(z); butterfly(v0); v1.resize(z); butterfly(v1); REP(i, z) v0[i] *= v1[i]; butterfly_inv(v0); v0.resize(n + m - 1); const mint iz = mint{ z }.inv(); REP(i, n + m - 1) v0[i] *= iz; if constexpr(std::convertible_to<R0, Res>) return v0; else return Res(ALL(v0)); } } // namespace uni #line 10 "convolution/sum.hpp" #line 12 "convolution/sum.hpp" namespace uni { template<class Res, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::same_as<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> && internal::static_modint_family<std::ranges::range_value_t<R0>> && std::convertible_to<std::ranges::range_value_t<R0>, std::ranges::range_value_t<Res>> Res convolution(R0&& v0, R1&& v1) { using mint = std::ranges::range_value_t<R0>; const auto n = std::ranges::ssize(v0); const auto m = std::ranges::ssize(v1); if(!n || !m) return {}; const auto z = to_signed(std::bit_ceil(to_unsigned(n + m - 1))); assert((mint::mod() - 1) % z == 0); // if(uni::min(n, m) <= 60) return convolution_naive<Res>(v0, v1); return convolution_fft<Res>(v0, v1); } template< u32 Mod = 998244353, class Res, std::ranges::sized_range R0, std::ranges::sized_range R1 > requires std::convertible_to<std::ranges::range_value_t<R0>, static_modint_32bit<Mod>> && std::convertible_to<std::ranges::range_value_t<R1>, static_modint_32bit<Mod>> && std::convertible_to<std::ranges::range_value_t<R0>, std::ranges::range_value_t<Res>> Res convolution(R0&& v0, R1&& v1) { using mint = static_modint_32bit<Mod>; const auto n = std::ranges::ssize(v0); const auto m = std::ranges::ssize(v1); if(!n || !m) return {}; const auto z = to_signed(std::bit_ceil(to_unsigned(n + m - 1))); assert((mint::mod() - 1) % z == 0); std::vector<mint> a2(n), b2(m); REP(i, n) a2[i] = mint{ v0[i] }; REP(i, m) b2[i] = mint{ v1[i] }; const auto c1 = convolution(a2, b2); Res c(n + m - 1); REP(i, n + m - 1) c[i] = c1[i].val(); return c; } template<class Res, std::ranges::sized_range R0, std::ranges::sized_range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> && std::integral<std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>> && ( std::integral<std::ranges::range_value_t<Res>> || internal::modint_family<std::ranges::range_value_t<Res>> ) && std::convertible_to<std::ranges::range_value_t<R0>, std::ranges::range_value_t<Res>> Res convolution(R0&& v0, R1&& v1) { using res_value_type = std::ranges::range_value_t<Res>; const auto n = std::ranges::ssize(v0); const auto m = std::ranges::ssize(v1); if(!n || !m) return {}; static constexpr i64 MOD0 = 167772161; static constexpr i64 MOD1 = 469762049; static constexpr i64 MOD2 = 754974721; static constexpr auto M0 = res_value_type{ MOD0 }; static constexpr auto M1 = res_value_type{ MOD1 }; static constexpr auto M2 = res_value_type{ MOD2 }; static constexpr auto M0M1 = M0 * M1; static constexpr auto M0M2 = M0 * M2; static constexpr auto M1M2 = M1 * M2; static constexpr auto M0M1M2 = M0 * M1 * M2; static constexpr u64 r0 = atcoder::internal::inv_gcd(MOD1 * MOD2, MOD0).second; static constexpr u64 r1 = atcoder::internal::inv_gcd(MOD0 * MOD2, MOD1).second; static constexpr u64 r2 = atcoder::internal::inv_gcd(MOD0 * MOD1, MOD2).second; static constexpr i64 i01 = atcoder::internal::inv_gcd(MOD0, MOD1).second; static constexpr i64 i02 = atcoder::internal::inv_gcd(MOD0, MOD2).second; static constexpr i64 i12 = atcoder::internal::inv_gcd(MOD1, MOD2).second; static constexpr i64 i02i12 = (i02 * i12) % MOD2; static constexpr size_t MAX_AB_BIT = 24; static_assert(MOD0 % (1ull << MAX_AB_BIT) == 1, "MOD0 isn't enough to support an array length of 2^24."); static_assert(MOD1 % (1ull << MAX_AB_BIT) == 1, "MOD1 isn't enough to support an array length of 2^24."); static_assert(MOD2 % (1ull << MAX_AB_BIT) == 1, "MOD2 isn't enough to support an array length of 2^24."); assert(n + m - 1 <= (1 << MAX_AB_BIT)); const auto c0 = convolution<MOD0, std::remove_cvref_t<R0>>(v0, v1); const auto c1 = convolution<MOD1, std::remove_cvref_t<R0>>(v0, v1); const auto c2 = convolution<MOD2, std::remove_cvref_t<R0>>(v0, v1); Res c(n + m - 1); REP(i, n + m - 1) { if constexpr(internal::modint_family<res_value_type>) { const auto c01 = ((c1[i] + MOD1 - c0[i]) * i01) % MOD1; const auto c012 = ((c2[i] + MOD2 - c0[i]) * i02i12 + (MOD2 - c01) * i12) % MOD2; c[i] = c0[i] + c01 * M0 + c012 * M0M1; } else { res_value_type x = 0; x += (c0[i] * r0) % MOD0 * M1M2; x += (c1[i] * r1) % MOD1 * M0M2; x += (c2[i] * r2) % MOD2 * M0M1; auto diff = c2[i] - uni::mod(to_signed(x), to_signed(MOD2)); if (diff < 0) diff += MOD2; static constexpr res_value_type offset[5] = { 0, 0, M0M1M2, 2 * M0M1M2, 3 * M0M1M2 }; x -= offset[diff % 5]; c[i] = x; } } return c; } template<std::ranges::range R0, std::ranges::range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> && internal::modint_family<std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>> auto convolution(R0&& v0, R1&& v1) { using common_type = std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>; return convolution<valarray<common_type>>(v0, v1); } template<u32 Mod = 998244353, std::ranges::range R0, std::ranges::range R1> requires std::common_with<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> && std::integral<std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>> && ( std::numeric_limits< std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>> >::digits <= 64 ) auto convolution(R0&& v0, R1&& v1) { using common_type = std::common_type_t<std::ranges::range_value_t<R0>, std::ranges::range_value_t<R1>>; return convolution<Mod, valarray<common_type>>(v0, v1); } } // namespace uni #line 2 "include/data_structures.hpp" #line 2 "data_structure/adaptor/set.hpp" #line 10 "data_structure/adaptor/set.hpp" #line 15 "data_structure/adaptor/set.hpp" #line 17 "data_structure/adaptor/set.hpp" #line 2 "data_structure/segment_tree.hpp" #line 11 "data_structure/segment_tree.hpp" #line 14 "data_structure/segment_tree.hpp" #line 2 "internal/point_reference.hpp" #line 6 "internal/point_reference.hpp" #line 9 "internal/point_reference.hpp" #line 11 "internal/point_reference.hpp" namespace uni { namespace internal { template<class Super, std::integral SizeType = typename Super::size_type> struct point_reference { using size_type = SizeType; using iterator = typename Super::iterator; protected: Super *const _super; const size_type _pos; point_reference(Super *const super, const size_type pos) noexcept(NO_EXCEPT) : _super(super), _pos(pos) {} inline auto index() noexcept(NO_EXCEPT) { return this->_pos; } }; } // namespace internal } // namespace uni #line 2 "internal/range_reference.hpp" #line 8 "internal/range_reference.hpp" #line 11 "internal/range_reference.hpp" #line 13 "internal/range_reference.hpp" namespace uni { namespace internal { template<class Super, std::integral SizeType = typename Super::size_type> struct range_reference { using size_type = SizeType; using iterator = Super::iterator; protected: Super *const _super; const size_type _begin, _end; range_reference(Super *const super, const size_type begin, const size_type end) noexcept(NO_EXCEPT) : _super(super), _begin(begin), _end(end) {} public: inline auto begin() const noexcept(NO_EXCEPT) { return std::ranges::next(std::ranges::begin(*this->_super), this->_begin); } inline auto end() const noexcept(NO_EXCEPT) { return std::ranges::next(std::ranges::begin(*this->_super), this->_end); } inline auto size() const noexcept(NO_EXCEPT) { return this->_end - this->_begin; } inline auto interval() const noexcept(NO_EXCEPT) { return std::make_pair(this->_begin, this->_end); } protected: inline auto sub_range(size_type l, size_type r) const noexcept(NO_EXCEPT) { l = _super->_positivize_index(l), r = _super->_positivize_index(r); assert(0 <= l and l <= r and r <= this->size()); return range_reference(_super, this->_begin + l, this->_begin + r); } public: template<uni::interval_notation rng = uni::interval_notation::right_open> inline auto range(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { if constexpr(rng == uni::interval_notation::right_open) return this->sub_range(l, r); if constexpr(rng == uni::interval_notation::left_open) return this->sub_range(l+1, r+1); if constexpr(rng == uni::interval_notation::open) return this->sub_range(l+1, r); if constexpr(rng == uni::interval_notation::closed) return this->sub_range(l, r+1); } inline auto range() const noexcept(NO_EXCEPT) { return range_reference(this->_begin, this->_end); } inline auto operator()(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return this->sub_range(l, r); } inline auto subseq(const size_type p, const size_type c) const noexcept(NO_EXCEPT) { return this->sub_range(p, p+c); } inline auto subseq(const size_type p) const noexcept(NO_EXCEPT) { return this->sub_range(p, this->size()); } }; } // namespace internal } // namespace uni #line 2 "internal/unconstructible.hpp" namespace uni { namespace internal { struct unconstructible { private: template<class... Args> unconstructible(Args...) = delete; }; } // namespace internal } // namespace uni #line 21 "data_structure/segment_tree.hpp" #line 25 "data_structure/segment_tree.hpp" namespace uni { namespace internal { namespace segment_tree_impl { // Thanks to: atcoder::segtree template<algebraic::internal::monoid Monoid> struct core { using size_type = internal::size_t; using operand = Monoid; protected: size_type _n = 0, _size = 0, _depth = 0; std::valarray<operand> _data; inline void _pull(const size_type k) noexcept(NO_EXCEPT) { this->_data[k] = this->_data[k << 1] + this->_data[k << 1 | 1]; } public: core() noexcept = default; explicit core(const size_type n) noexcept(NO_EXCEPT) : _n(n), _size(std::bit_ceil(uni::to_unsigned(n))), _depth(std::countr_zero(uni::to_unsigned(this->_size))), _data(this->_size << 1) {} inline size_type size() const noexcept(NO_EXCEPT) { return this->_n; } inline size_type allocated() const noexcept(NO_EXCEPT) { return this->_values.size(); } inline size_type depth() const noexcept(NO_EXCEPT) { return this->_depth; } inline operand fold_all() const noexcept(NO_EXCEPT) { return this->_data[1]; } template<std::input_iterator I, std::sentinel_for<I> S> inline void assign(I first, S last) noexcept(NO_EXCEPT) { if constexpr(std::sized_sentinel_for<S, I>) { assert(std::ranges::distance(first, last) == this->_n); } { size_type p = 0; for(auto itr=first; itr!=last; ++itr, ++p) this->_data[this->_size + p] = static_cast<operand>(*itr); } REPD(p, 1, this->_size) this->_pull(p); } inline void fill(const operand& v = operand()) noexcept(NO_EXCEPT) { REP(p, this->_n) this->_data[this->_size + p] = v; REPD(p, 1, this->_size) this->_pull(p); } inline void add(size_type p, const operand& x) noexcept(NO_EXCEPT) { this->set(p, this->_data[p + this->_size] + x); } inline void set(size_type p, const operand& x) noexcept(NO_EXCEPT) { p += this->_size; this->_data[p] = x; FOR(i, 1, this->_depth) this->_pull(p >> i); } inline operand get(size_type p) const noexcept(NO_EXCEPT) { return this->_data[p + this->_size]; } inline operand fold(size_type l, size_type r) const noexcept(NO_EXCEPT) { operand sml, smr; l += this->_size; r += this->_size; while(l < r) { if(l & 1) sml = sml + this->_data[l++]; if(r & 1) smr = this->_data[--r] + smr; l >>= 1; r >>= 1; } return sml + smr; } template<class F> inline size_type max_right(size_type l, F&& f) const noexcept(NO_EXCEPT) { assert(0 <= l && l <= this->_n); assert(f(operand{})); if(l == this->_n) return this->_n; l += this->_size; operand acc; do { while((l & 1) == 0) l >>= 1; if(!f(acc + this->_data[l])) { while(l < this->_size) { l <<= 1; if(f(acc + this->_data[l])) { acc = acc + this->_data[l]; ++l; } } return l - this->_size; } acc = acc + this->_data[l]; ++l; } while((l & -l) != l); return this->_n; } template<class F> inline size_type min_left(size_type r, F&& f) const noexcept(NO_EXCEPT) { assert(0 <= r && r <= this->_n); assert(f(operand{})); if (r == 0) return 0; r += this->_size; operand acc; do { --r; while(r > 1 && (r & 1)) r >>= 1; if(!f(this->_data[r] + acc)) { while(r < this->_size) { r = (r << 1 | 1); if(f(this->_data[r] + acc)) { acc = this->_data[r] + acc; --r; } } return r + 1 - this->_size; } acc = this->_data[r] + acc; } while((r & -r) != r); return 0; } }; } // namespace segment_tree_impl } // namespace internal template<class T> struct segment_tree : internal::unconstructible {}; template<algebraic::internal::monoid Monoid> struct segment_tree<Monoid> { private: using core = typename internal::segment_tree_impl::core<Monoid>; core _impl; public: using value_type = Monoid; using size_type = typename core::size_type; private: inline auto _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->_impl.size() + p : p; } public: segment_tree() noexcept(NO_EXCEPT) : _impl() {}; explicit segment_tree(const size_type n, const value_type& v = value_type()) noexcept(NO_EXCEPT) : _impl(n) { this->_impl.fill(v); } template<std::convertible_to<value_type> T> segment_tree(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) : segment_tree(ALL(init_list)) {} template<std::input_iterator I, std::sized_sentinel_for<I> S> segment_tree(I first, S last) noexcept(NO_EXCEPT) : segment_tree(static_cast<size_type>(std::ranges::distance(first, last))) { this->assign(first, last); } template<std::ranges::input_range R> explicit segment_tree(R&& range) noexcept(NO_EXCEPT) : segment_tree(ALL(range)) {} inline auto size() const noexcept(NO_EXCEPT) { return this->_impl.size(); } inline auto allocated() const noexcept(NO_EXCEPT) { return this->_impl.allocated(); } inline auto depth() const noexcept(NO_EXCEPT) { return this->_impl.depth(); } template<std::convertible_to<value_type> T> inline auto& assign(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) { return this->assign(ALL(init_list)); } template<std::input_iterator I, std::sentinel_for<I> S> inline auto& assign(I first, S last) noexcept(NO_EXCEPT) { this->_impl.assign(first, last); return *this; } template<std::ranges::input_range R> inline auto& assign(R&& range) noexcept(NO_EXCEPT) { return this->assign(ALL(range)); } inline auto& fill(const value_type& v = value_type()) noexcept(NO_EXCEPT) { this->_impl.fill(v); return *this; } inline bool empty() const noexcept(NO_EXCEPT) { return this->_impl.size() == 0; } struct point_reference : internal::point_reference<segment_tree> { point_reference(segment_tree *const super, const size_type p) noexcept(NO_EXCEPT) : internal::point_reference<segment_tree>(super, super->_positivize_index(p)) { assert(0 <= this->_pos && this->_pos < this->_super->size()); } operator value_type() const noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } auto val() const noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } inline auto& operator=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->set(this->_pos, v); return *this; } inline auto& operator+=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->add(this->_pos, v); return *this; } }; struct range_reference : internal::range_reference<segment_tree> { range_reference(segment_tree *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<segment_tree>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->size()); } inline auto fold() noexcept(NO_EXCEPT) { if(this->_begin == 0 and this->_end == this->_super->size()) return this->_super->fold(); return this->_super->fold(this->_begin, this->_end); } }; inline auto& add(const size_type p, const value_type& x) noexcept(NO_EXCEPT) { assert(0 <= p && p < this->_impl.size()); this->_impl.add(p, x); return *this; } inline auto& set(const size_type p, const value_type& x) noexcept(NO_EXCEPT) { assert(0 <= p && p < this->_impl.size()); this->_impl.set(p, x); return *this; } inline auto get(const size_type p) const noexcept(NO_EXCEPT) { assert(0 <= p && p < this->_impl.size()); return this->_impl.fold(p, p+1); } inline auto operator[](const size_type p) noexcept(NO_EXCEPT) { return point_reference(this, p); } inline auto operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto fold(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { assert(0 <= l && l <= r && r <= this->_impl.size()); return this->_impl.fold(l, r); } inline auto fold(const size_type r) const noexcept(NO_EXCEPT) { assert(0 <= r && r <= this->_impl.size()); return this->_impl.fold(0, r); } inline auto fold() const noexcept(NO_EXCEPT) { return this->_impl.fold_all(); } template<bool (*f)(value_type)> inline auto max_right(const size_type l) const noexcept(NO_EXCEPT) { return this->_impl.max_right(l, [](value_type x) { return f(x); }); } template<class F> inline auto max_right(const size_type l, F&& f) const noexcept(NO_EXCEPT) { return this->_impl.max_right(l, std::forward<F>(f)); } template<bool (*f)(value_type)> inline auto min_left(const size_type r) const noexcept(NO_EXCEPT) { return this->_impl.min_left(r, [](value_type x) { return f(x); }); } template<class F> inline auto min_left(const size_type r, F&& f) const noexcept(NO_EXCEPT) { return this->_impl.min_left(r, std::forward<F>(f)); } struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, const segment_tree, iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, this->_impl.size()); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } }; template<actions::internal::operatable_action Action> struct segment_tree<Action> : segment_tree<typename Action::operand> { using segment_tree<typename Action::operand>::segment_tree; }; } // namespace uni #line 26 "data_structure/adaptor/set.hpp" namespace uni { namespace internal { template< template<class...> class Tree, template<class...> class Action > requires actions::internal::action<Action<internal::size_t>> struct set_adaptor_impl { using size_type = internal::size_t; using key_type = internal::size_t; using value_type = internal::size_t; protected: using impl_data_type = algebraic::combined<algebraic::addition<value_type>, algebraic::minimum<value_type>>; using impl_tree = Tree< std::conditional_t< internal::available_with< Tree, Action<impl_data_type> >, Action<impl_data_type>, actions::range_sum<impl_data_type> > >; impl_tree _data; size_type _elem = 0; public: set_adaptor_impl(const size_type sup) noexcept(NO_EXCEPT) : _data(sup) {}; inline size_type size() const noexcept(NO_EXCEPT) { return this->_data.fold(); } inline bool empty() const noexcept(NO_EXCEPT) { return this->size() == 0; } inline size_type count(const key_type& k) const noexcept(NO_EXCEPT) { return this->_data.get(k).val()->first.val(); } inline bool contains(const key_type& k) const noexcept(NO_EXCEPT) { return this->_data.get(k).val()->first.val() > 0; } inline value_type mex(const key_type& base = 0) const noexcept(NO_EXCEPT) { return this->_data.max_right(base, [](const auto& p) { return p.val()->second.val() > 0; }); } inline std::optional<value_type> next(const key_type& k, const size_type count = 0) const noexcept(NO_EXCEPT) { const auto v = this->_data.max_right(k, [count](const auto& p) { return p.val()->first.val() <= count; }); if(v == this->_data.size()) return {}; return { v }; } inline std::optional<value_type> prev(const key_type& k, const size_type count = 0) const noexcept(NO_EXCEPT) { const auto v = this->_data.min_left(k + 1, [count](const auto& p) { return p.val()->first.val() <= count; }); if(v == 0) return {}; return { v - 1 }; } inline auto kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { return this->next(0, k); } inline auto kth_largest(const size_type k) const noexcept(NO_EXCEPT) { return this->prev(this->_data.size()-1, k); } inline value_type min() const noexcept(NO_EXCEPT) { return this->kth_smallest(0); } inline value_type max() const noexcept(NO_EXCEPT) { return this->kth_largest(0); } inline size_type count_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_data.fold(0, v).val()->first.val(); } inline size_type count_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_data.fold(v+1, this->_data.size()).val()->first.val(); } inline size_type count_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_data.fold(0, v+1).val()->first.val(); } inline size_type count_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_data.fold(v, this->_data.size()).val()->first.val(); } template<comparison com = comparison::equal_to> inline size_type count(const value_type& v) const noexcept(NO_EXCEPT) { if constexpr(com == comparison::eq) return this->count(v); if constexpr(com == comparison::under) return this->count_under(v); if constexpr(com == comparison::over) return this->count_over(v); if constexpr(com == comparison::or_under) return this->count_or_under(v); if constexpr(com == comparison::or_over) return this->count_or_over(v); assert(false); } inline const auto& _debug() const noexcept(NO_EXCEPT) { return this->_data; } }; }; template<template<class...> class Tree = uni::segment_tree> struct set_adaptor : internal::set_adaptor_impl<Tree, actions::range_set_range_sum> { using size_type = internal::size_t; using key_type = internal::size_t; using value_type = size_type; protected: using Base = internal::set_adaptor_impl<Tree, actions::range_set_range_sum>; using impl_data_type = typename Base::impl_data_type; public: set_adaptor() noexcept(NO_EXCEPT) = default; set_adaptor(const size_type sup) noexcept(NO_EXCEPT) : Base(sup) {}; template<std::input_iterator I, std::sentinel_for<I> S> set_adaptor(I first, S last) noexcept(NO_EXCEPT) : set_adaptor(*std::ranges::max_element(first, last) + 1) { valarray<bool> bits(this->_data.size()); REP(itr, first, last) { assert(0 <= *itr && *itr < this->_data.size()); bits[*itr] = true; } this->build_from_bits(ALL(bits)); }; template<std::ranges::input_range R> set_adaptor(R&& range) noexcept(NO_EXCEPT) : set_adaptor(ALL(range)) {} template<std::input_iterator I, std::sentinel_for<I> S> inline auto& build_from_bits(I first, S last) noexcept(NO_EXCEPT) { if constexpr(std::sized_sentinel_for<S, I>) { assert(std::ranges::distance(first, last) == this->_data.size()); } this->_data.assign(first, last); return *this; }; template<std::ranges::input_range R> inline auto& build_from_bits(R&& range) noexcept(NO_EXCEPT) { return this->build_from_bits(ALL(range)); } inline bool insert(const key_type& k) noexcept(NO_EXCEPT) { assert(0 <= k && k < this->_data.size()); const bool res = !this->_data.get(k).val()->first.val(); if(res) this->_data.set(k, impl_data_type{ 1 }); return res; } inline bool remove(const key_type& k) noexcept(NO_EXCEPT) { assert(0 <= k && k < this->_data.size()); const bool res = this->_data.get(k).val()->first.val(); if(res) this->_data.set(k, impl_data_type{ 0 }); return res; } }; template<template<class...> class Tree = uni::segment_tree, std::integral Size = std::int64_t> struct multiset_adaptor : internal::set_adaptor_impl<Tree, actions::range_add_range_sum> { using size_type = Size; using key_type = internal::size_t; using value_type = key_type; private: using Base = internal::set_adaptor_impl<Tree, actions::range_add_range_sum>; using impl_data_type = typename Base::impl_data_type; public: multiset_adaptor(const size_type sup) noexcept(NO_EXCEPT) : Base(sup) {}; template<std::input_iterator I, std::sentinel_for<I> S> multiset_adaptor(I first, S last) noexcept(NO_EXCEPT) : Base(*std::ranges::max_element(first, last) + 1) { vector<size_type> cnts(this->_data.size()); REP(itr, first, last) { assert(0 <= *itr && *itr < this->_data.size()); cnts[*itr]++; } this->build_from_histogram(ALL(cnts)); }; template<std::ranges::input_range R> multiset_adaptor(R&& range) noexcept(NO_EXCEPT) : multiset_adaptor(ALL(range)) {} template<std::input_iterator I, std::sentinel_for<I> S> inline auto& build_from_histogram(I first, S last) noexcept(NO_EXCEPT) { if constexpr(std::sized_sentinel_for<S, I>) { assert(std::ranges::distance(first, last) == this->_data.size()); } this->_data.assign(first, last); return *this; }; template<std::ranges::input_range R> inline auto& build_from_histogram(R&& range) noexcept(NO_EXCEPT) { return this->build_from_histogram(ALL(range)); } inline void insert(const key_type& k, const size_type count = 1) noexcept(NO_EXCEPT) { assert(0 <= k && k < this->_data.size()); assert(0 <= count); const auto cur = this->_data.get(k); const auto num = cur.val()->first.val(); this->_data.set(k, impl_data_type{ num + count }); this->_elem += count; } inline void remove(const key_type& k, const size_type count = 1) noexcept(NO_EXCEPT) { assert(0 <= k && k < this->_data.size()); const auto cur = this->_data.get(k); const auto num = cur.val()->first.val(); assert(0 <= count && count <= num); this->_data.set(k, impl_data_type{ num - count }); } }; } // namespace uni #line 4 "include/data_structures.hpp" #line 2 "data_structure/bit_vector.hpp" #line 9 "data_structure/bit_vector.hpp" #line 14 "data_structure/bit_vector.hpp" #line 16 "data_structure/bit_vector.hpp" namespace uni { // Thanks to: https://github.com/NyaanNyaan/library/blob/master/data-structure-2d/wavelet-matrix.hpp struct bit_vector { using size_type = std::uint_fast32_t; private: static constexpr size_type WORDSIZE = 64; std::vector<std::uint64_t> _block; std::vector<size_type> _count; size_type _n, _zeros; public: bit_vector(const size_type n = 0) noexcept(NO_EXCEPT) { this->init(n); } template<std::input_iterator I, std::sentinel_for<I> S> bit_vector(I first, S last) noexcept(NO_EXCEPT) : bit_vector(std::ranges::distance(first, last)) { size_type pos = 0; for(auto itr=first; itr != last; ++pos, ++itr) if(*itr) this->set(pos); } template<std::ranges::input_range R> bit_vector(R&& range) noexcept(NO_EXCEPT) : bit_vector(ALL(range)) {} template<class T> bit_vector(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) : bit_vector(ALL(init_list)) {} inline constexpr size_type size() const noexcept(NO_EXCEPT) { return this->_n; } inline constexpr size_type zeros() const noexcept(NO_EXCEPT) { return this->_zeros; } inline constexpr size_type ones() const noexcept(NO_EXCEPT) { return this->_n - this->_zeros; } inline void set(const size_type k) noexcept(NO_EXCEPT) { this->_block[k / WORDSIZE] |= (1LL << (k % WORDSIZE)); } inline bool get(const size_type k) const noexcept(NO_EXCEPT) { return 1U & static_cast<std::uint32_t>(this->_block[k / WORDSIZE] >> (k % WORDSIZE)); } __attribute__((optimize("O3", "unroll-loops"))) inline void init(const size_type n) noexcept(NO_EXCEPT) { this->_n = this->_zeros = n; this->_block.resize(this->_n / WORDSIZE + 1, 0); this->_count.resize(this->_block.size(), 0); } inline void build() noexcept(NO_EXCEPT) { for(auto k = 1UL; k < this->_block.size(); ++k) { this->_count[k] = this->_count[k-1] + static_cast<size_type>(std::popcount(this->_block[k-1])); } this->_zeros = this->rank0(this->_n); } inline size_type rank1(const size_type k) const noexcept(NO_EXCEPT) { return this->_count[k / WORDSIZE] + static_cast<size_type>(std::popcount(uni::clear_higher_bits(this->_block[k / WORDSIZE], k % WORDSIZE))); } inline size_type rank0(const size_type k) const noexcept(NO_EXCEPT) { return k - this->rank1(k); } template<bool BIT> inline size_type rank(const size_type k) const noexcept(NO_EXCEPT) { if constexpr(BIT) return this->rank0(k); else return this->rank1(k); } template<bool BIT> inline size_type select(const size_type rank) const noexcept(NO_EXCEPT) { if constexpr(BIT) { if(rank >= this->ones()) return this->_n; } else { if(rank >= this->zeros()) return this->_n; } size_type index = 0; { size_type ng = static_cast<size_type>(this->_count.size()); while(ng - index > 1) { size_type mid = (ng + index) / 2; size_type cnt = this->_count[mid]; if constexpr(!BIT) cnt = mid * WORDSIZE - cnt; (cnt <= rank ? index : ng) = mid; } } const size_type base = index * WORDSIZE; if constexpr(BIT) { return base + select64(this->_block[index], rank - this->_count[index]); } else { return base + select64(~this->_block[index], rank - (base - this->_count[index])); } } inline size_type select0(const size_type k) const noexcept(NO_EXCEPT) { return this->select<false>(k); } inline size_type select1(const size_type k) const noexcept(NO_EXCEPT) { return this->select<true>(k); } struct iterator; private: using iterator_interface = internal::container_iterator_interface<bool, const bit_vector, iterator>; public: struct iterator : iterator_interface { iterator() noexcept = default; iterator(const bit_vector *const ref, const size_type pos) noexcept(NO_EXCEPT) : bit_vector::iterator_interface(ref, static_cast<difference_type>(pos)) {} inline bool operator*() const noexcept(NO_EXCEPT) { return this->ref()->get(this->pos()); } }; inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, this->size()); } }; } // namespace uni #line 2 "data_structure/disjoint_set.hpp" #line 8 "data_structure/disjoint_set.hpp" #line 12 "data_structure/disjoint_set.hpp" #line 15 "data_structure/disjoint_set.hpp" #line 17 "data_structure/disjoint_set.hpp" namespace uni { //Thanks to: atcoder::disjoint_set struct disjoint_set { using size_type = internal::size_t; private: size_type _n = 0, _group_count = 0; // root node: -1 * component size // otherwise: parent std::vector<size_type> _parent_or_size; public: disjoint_set() noexcept = default; explicit disjoint_set(const size_type n) noexcept(NO_EXCEPT) : _n(n), _group_count(n), _parent_or_size(n, -1) {} inline auto size() const noexcept(NO_EXCEPT) { return this->_n; } inline auto group_count() const noexcept(NO_EXCEPT) { return this->_group_count; } inline auto merge(const size_type a, const size_type b) noexcept(NO_EXCEPT) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); size_type x = this->leader(a), y = this->leader(b); if (x == y) return x; --this->_group_count; if (-this->_parent_or_size[x] < -this->_parent_or_size[y]) std::swap(x, y); this->_parent_or_size[x] += this->_parent_or_size[y]; this->_parent_or_size[y] = x; return x; } inline bool same(const size_type a, const size_type b) noexcept(NO_EXCEPT) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); return this->leader(a) == this->leader(b); } inline size_type leader(const size_type a) noexcept(NO_EXCEPT) { assert(0 <= a && a < _n); if(this->_parent_or_size[a] < 0) return a; return this->_parent_or_size[a] = this->leader(this->_parent_or_size[a]); } inline auto size(const size_type a) noexcept(NO_EXCEPT) { assert(0 <= a && a < _n); return -this->_parent_or_size[this->leader(a)]; } inline auto groups() noexcept(NO_EXCEPT) { vector<size_type> leader_buf(_n), group_size(_n); REP(i, this->_n) { leader_buf[i] = this->leader(i); group_size[leader_buf[i]]++; } vector<vector<size_type>> result(_n); REP(i, this->_n) result[i].reserve(group_size[i]); REP(i, this->_n) result[leader_buf[i]].push_back(i); { const auto range = std::ranges::remove_if(result, [&](const auto& v) { return v.empty(); }); result.erase(ALL(range)); } return result; } }; } // namespace uni #line 2 "data_structure/disjoint_sparse_table.hpp" #line 12 "data_structure/disjoint_sparse_table.hpp" #line 19 "data_structure/disjoint_sparse_table.hpp" #line 21 "data_structure/disjoint_sparse_table.hpp" #line 24 "data_structure/disjoint_sparse_table.hpp" namespace uni { namespace internal { namespace disjoint_sparse_table_impl { // Thanks to: https://noshi91.hatenablog.com/entry/2018/05/08/183946 template<algebraic::internal::semigroup Operand> struct core { using size_type = internal::size_t; using operand = Operand; using iterator = std::vector<std::vector<Operand>>; size_type _n = 0, _depth = 0; bool _built = false; protected: std::vector<std::vector<operand>> _table = {}; public: explicit core(const size_type n = 0) noexcept(NO_EXCEPT) : _n(n) { this->_depth = std::bit_width<std::make_unsigned_t<size_type>>(n); this->_table.resize(this->_depth+1, std::vector<operand>(n)); } template<std::input_iterator I, std::sized_sentinel_for<I> S> core(I first, S last) noexcept(NO_EXCEPT) : core(static_cast<size_type>(std::ranges::distance(first, last))) { std::ranges::copy(first, last, this->_table.begin()->begin()); } template<bool FORCE = false> inline auto& build() noexcept(NO_EXCEPT) { if(!FORCE and this->_built) return *this; FOR(i, 2, this->_depth) { const size_type len = 1 << i; for(size_type l = 0, m = (len >> 1); m < this->_n; l += len, m = l + (len >> 1)) { this->_table[i - 1][m - 1] = this->_table.front()[m - 1]; REPD(j, l, m-1) { this->_table[i - 1][j] = this->_table.front()[j] + this->_table[i - 1][j + 1]; } this->_table[i - 1][m] = this->_table.front()[m]; REP(j, m + 1, std::min(l + len, this->_n)) { this->_table[i - 1][j] = this->_table[i - 1][j - 1] + this->_table.front()[j]; } } } this->_built = true; return *this; } inline auto& raw() noexcept(NO_EXCEPT) { this->_built = false; return this->_table.front(); } inline const auto& raw() const noexcept(NO_EXCEPT) { return this->_table.front(); } inline auto& data() noexcept(NO_EXCEPT) { return this->_table; } inline const auto& data() const noexcept(NO_EXCEPT) { return this->_table; } size_type size() const noexcept(NO_EXCEPT) { return this->_n; } operand fold(const size_type l, size_type r) { if(l == r) return operand{}; if(l == --r) return this->_table.front()[l]; this->build(); const size_type p = highest_bit_pos<std::make_unsigned_t<size_type>>(l ^ r); return this->_table[p][l] + this->_table[p][r]; } }; } // namespace disjoint_sparse_table_impl } // namespace internal template<class> struct disjoint_sparse_table : internal::unconstructible {}; template<algebraic::internal::semigroup Semigroup> struct disjoint_sparse_table<Semigroup> { private: using core = internal::disjoint_sparse_table_impl::core<Semigroup>; using iterator = core::iterator; core _impl; public: using value_type = Semigroup; using size_type = core::size_type; protected: inline auto _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->_impl.size() + p : p; } public: explicit disjoint_sparse_table(const size_type n, const value_type& val = value_type()) noexcept(NO_EXCEPT) : _impl(n) { this->_impl.data().begin()->assign(n, val); } template<std::input_iterator I, std::sized_sentinel_for<I> S> disjoint_sparse_table(I first, S last) noexcept(NO_EXCEPT) : _impl(first, last) {} template<std::ranges::input_range R> explicit disjoint_sparse_table(R&& range) noexcept(NO_EXCEPT) : _impl(std::ranges::begin(range), std::ranges::end(range)) {} inline auto& raw() noexcept(NO_EXCEPT) { return this->_impl.raw(); } inline const auto& raw() const noexcept(NO_EXCEPT) { return this->_impl.raw(); } inline const auto& data() const noexcept(NO_EXCEPT) { return this->impl.data(); } inline auto size() const noexcept(NO_EXCEPT) { return this->_impl.size(); } friend internal::range_reference<disjoint_sparse_table>; struct range_reference : internal::range_reference<disjoint_sparse_table> { range_reference(disjoint_sparse_table *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<disjoint_sparse_table>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->size()); } inline auto fold() noexcept(NO_EXCEPT) { return this->_super->fold(this->_begin, this->_end); } }; inline auto fold(size_type l, size_type r) noexcept(NO_EXCEPT) { l = this->_positivize_index(l), r = this->_positivize_index(r); assert(0 <= l && l <= r && r <= this->size()); return this->_impl.fold(l, r); } inline auto fold() noexcept(NO_EXCEPT) { return this->fold(0, this->size()); } inline auto operator[](const size_type index) const noexcept(NO_EXCEPT) { return this->_impl.data().front()[index]; } inline auto operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto begin() const noexcept(NO_EXCEPT) { return this->_impl.data().begin()->begin(); } inline auto end() const noexcept(NO_EXCEPT) { return this->_impl.data().begin()->end(); } inline auto rbegin() const noexcept(NO_EXCEPT) { return this->_impl.data().begin()->rbegin(); } inline auto rend() const noexcept(NO_EXCEPT) { return this->_impl.data().begin()->rend(); } }; template<actions::internal::operatable_action Action> struct disjoint_sparse_table<Action> : disjoint_sparse_table<typename Action::operand> { using disjoint_sparse_table<typename Action::operand>::disjoint_sparse_table; }; } // namespace uni #line 2 "data_structure/dynamic_segment_tree.hpp" #include <memory_resource> #line 6 "data_structure/dynamic_segment_tree.hpp" #include <memory> #line 13 "data_structure/dynamic_segment_tree.hpp" #line 16 "data_structure/dynamic_segment_tree.hpp" #line 23 "data_structure/dynamic_segment_tree.hpp" #line 2 "data_structure/internal/node_handler.hpp" #line 5 "data_structure/internal/node_handler.hpp" #line 7 "data_structure/internal/node_handler.hpp" namespace uni { namespace node_handlers { namespace internal { template<class Allocator, class NodeType> struct base_handler { using allocator_type = Allocator; protected: using allocator_traits = std::allocator_traits<allocator_type>; using node_allocator_type = allocator_traits::template rebind_alloc<NodeType>; using node_allocator_traits = std::allocator_traits<node_allocator_type>; [[no_unique_address]] node_allocator_type _allocator; public: base_handler(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _allocator(allocator) {} base_handler(const base_handler& source) noexcept(NO_EXCEPT) : _allocator(node_allocator_traits::select_on_container_copy_construction(source._allocator)) {} base_handler(base_handler&& source) noexcept = default; auto& operator=(const base_handler& source) noexcept(NO_EXCEPT) { if(&source != this) { if constexpr(allocator_traits::propagate_on_container_copy_assignment::value) { this->_allocator = source._allocator; } } return *this; } auto& operator=(base_handler&& source) noexcept(NO_EXCEPT) { if(&source != this) { if constexpr(allocator_traits::propagate_on_container_move_assignment::value) { this->_allocator = source._allocator; } } return *this; } }; } // namespace internal template<class Allocator> struct cloneable { template<class NodeType> struct handler : internal::base_handler<Allocator, NodeType> { using internal::base_handler<Allocator, NodeType>::base_handler; using node_type = NodeType; using node_pointer = std::shared_ptr<node_type>; inline static node_pointer nil = std::make_shared<node_type>(); template<class... Args> inline auto create(Args&&... args) noexcept(NO_EXCEPT) { return std::allocate_shared<node_type>(this->_allocator, std::forward<Args>(args)...); } inline auto clone(const node_pointer& ptr) noexcept(NO_EXCEPT) { return this->create(*ptr); } inline constexpr bool disposable(const node_pointer&) const noexcept { return false; } inline constexpr void dispose(const node_pointer&) const noexcept {} }; }; template<class Allocator> struct reusing { template<class NodeType> struct handler : internal::base_handler<Allocator, NodeType> { using node_type = NodeType; using node_pointer = std::add_pointer_t<node_type>; private: using base = internal::base_handler<Allocator, NodeType>; using node_allocator_traits = typename base::node_allocator_traits; inline static int _instance_count = 0; public: using base::base; using allocator_type = typename base::allocator_type; inline static node_pointer nil; handler(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : base(allocator) { if(handler::_instance_count++ == 0) { handler::nil = new node_type{}; } } ~handler() noexcept { if(--handler::_instance_count == 0) { delete handler::nil; } } template<class... Args> inline auto create(Args&&... args) noexcept(NO_EXCEPT) { node_pointer node = node_allocator_traits::allocate(this->_allocator, 1); node_allocator_traits::construct(this->_allocator, node, std::forward<Args>(args)...); return node; } inline auto clone(const node_pointer ptr) const noexcept { return ptr; } inline bool disposable(const node_pointer node) const noexcept(NO_EXCEPT) { return node != handler::nil; } inline void dispose(const node_pointer node) noexcept(NO_EXCEPT) { node_allocator_traits::destroy(this->_allocator, node); node_allocator_traits::deallocate(this->_allocator, node, 1); } }; }; } // namespace node_handlers } // namespace uni #line 25 "data_structure/dynamic_segment_tree.hpp" #line 28 "data_structure/dynamic_segment_tree.hpp" #line 30 "data_structure/dynamic_segment_tree.hpp" namespace uni { namespace internal { namespace dynamic_segment_tree_impl { // Thanks to: atcoder::segtree template<algebraic::internal::monoid Monoid, class NodeHandler> struct core { using size_type = internal::size_t; using operand = Monoid; struct node_type; using node_handler = NodeHandler::template handler<node_type>; using allocator_type = typename node_handler::allocator_type; using node_pointer = typename node_handler::node_pointer; protected: [[no_unique_address]] node_handler _node_handler; public: explicit core(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _node_handler(allocator) {} core(const core&, const allocator_type& allocator) noexcept(NO_EXCEPT) : _node_handler(allocator) {} core(core&&, const allocator_type& allocator) noexcept(NO_EXCEPT) : _node_handler(allocator) {} struct node_type { size_type index; operand val, acc; node_pointer left = node_handler::nil, right = node_handler::nil; node_type() noexcept = default; node_type(const size_type _index, const operand& _val) noexcept(NO_EXCEPT) : index(_index), val(_val), acc(_val) {} }; protected: inline void pull(const node_pointer& tree) const noexcept(NO_EXCEPT) { tree->acc = tree->left->acc + tree->val + tree->right->acc; } inline void dispose(const node_pointer& tree) noexcept(NO_EXCEPT) { if(this->_node_handler.disposable(tree)) { this->dispose(tree->left); this->dispose(tree->right); this->_node_handler.dispose(tree); } } public: template<std::random_access_iterator I> node_pointer build(const size_type lower, const size_type upper, const size_type l, const size_type r, I first) noexcept(NO_EXCEPT) { const size_type middle = (lower + upper) >> 1; const auto itr = std::ranges::next(first, middle); if(middle < l || r <= middle) return node_handler::nil; node_pointer node = this->_node_handler.create(middle, *itr); node->left = this->build(lower, middle, l, middle, first); node->right = this->build(middle, upper, middle + 1, r, first); this->pull(node); return node; } template<std::random_access_iterator I, std::sentinel_for<I> S> node_pointer build(I first, S last) noexcept(NO_EXCEPT) { const size_type size = std::ranges::distance(first, last); return this->build(0, size, 0, size, first); } void set(node_pointer& tree, const size_type lower, const size_type upper, size_type pos, operand val) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) { tree = this->_node_handler.create(pos, val); return; } tree = this->_node_handler.clone(tree); if(tree->index == pos) { tree->val = val; this->pull(tree); return; } const size_type middle = (lower + upper) >> 1; if(pos < middle) { if(tree->index < pos) std::swap(tree->index, pos), std::swap(tree->val, val); this->set(tree->left, lower, middle, pos, val); } else { if(pos < tree->index) std::swap(tree->index, pos), std::swap(tree->val, val); this->set(tree->right, middle, upper, pos, val); } this->pull(tree); } operand get(const node_pointer& tree, const size_type lower, const size_type upper, const size_type pos) const noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return {}; if(tree->index == pos) return tree->val; const size_type middle = (lower + upper) >> 1; if(pos < middle) return this->get(tree->left, lower, middle, pos); else return this->get(tree->right, middle, upper, pos); } operand fold(const node_pointer& tree, const size_type lower, const size_type upper, const size_type l, const size_type r) const noexcept(NO_EXCEPT) { if(tree == node_handler::nil || upper <= l || r <= lower) return {}; if(l <= lower && upper <= r) return tree->acc; const size_type middle = (lower + upper) >> 1; operand val = this->fold(tree->left, lower, middle, l, r); if(l <= tree->index && tree->index < r) val = val + tree->val; return val + this->fold(tree->right, middle, upper, l, r); } void clear(const node_pointer& tree, const size_type lower, const size_type upper, const size_type l, const size_type r) const noexcept(NO_EXCEPT) { if(tree == node_handler::nil || upper <= l || r <= lower) return; if(l <= lower && upper <= r) { this->dispose(tree); tree = node_handler::nil; return; } const size_type middle = (lower + upper) >> 1; this->clear(tree->left, lower, middle, l, r); this->clear(tree->right, middle, upper, l, r); this->pull(tree); } template<class F> size_type max_right(const node_pointer& tree, const size_type lower, const size_type upper, const size_type l, F&& f, operand& acc) const { if(tree == node_handler::nil || upper <= l) return -1; if(f(acc + tree->acc)) { acc = acc + tree->acc; return -1; } const size_type middle = (lower + upper) >> 1; const size_type res = this->max_right(tree->left, lower, middle, l, f, acc); if(res != -1) return res; if(l <= tree->index && !f(acc = acc + tree->val)) return tree->index; return this->max_right(tree->right, middle, upper, l, std::forward<F>(f), acc); } template<class F> size_type min_left(const node_pointer& tree, const size_type lower, const size_type upper, const size_type r, F&& f, operand& acc) const { if(tree == node_handler::nil || r <= lower) return 0; if(f(tree->acc + acc)) { acc = tree->acc + acc; return 0; } const size_type middle = (lower + upper) >> 1; const size_type res = this->min_left(tree->right, middle, upper, r, f, acc); if(res != 0) return res; if(tree->index < r && !f(acc = tree->val + acc)) { return tree->index + 1; } return this->min_left(tree->left, lower, middle, r, std::forward<F>(f), acc); } public: debugger::debug_t dump_rich(const node_pointer& tree, const std::string prefix = " ", const int dir = 0) const { if(!tree || tree == node_handler::nil) return prefix + "\n"; const auto left = this->dump_rich(tree->left, prefix + (dir == 1 ? "| " : " "), -1); const auto here = prefix + "--+ " + debugger::dump(tree->index) + " : " + debugger::dump(tree->val) + "\n"; const auto right = this->dump_rich(tree->right, prefix + (dir == -1 ? "| " : " "), 1); return left + here + right; } debugger::debug_t _debug(const node_pointer tree) const { if(!tree || tree == node_handler::nil) return ""; return "(" + this->_debug(tree->left) + " " + debugger::dump(tree->index) + " : " + debugger::dump(tree->val) + this->_debug(tree->right) + ")"; } }; } // namespace dynamic_segment_tree_impl } // namespace internal template<class T, class = node_handlers::reusing<std::allocator<T>>> struct dynamic_segment_tree : internal::unconstructible {}; template<actions::internal::operatable_action Action, class NodeHandler> struct dynamic_segment_tree<Action, NodeHandler> : private internal::dynamic_segment_tree_impl::core<typename Action::operand, NodeHandler> { private: using core = typename internal::dynamic_segment_tree_impl::core<typename Action::operand, NodeHandler>; public: using value_type = typename core::operand; using size_type = typename core::size_type; using node_handler = typename core::node_handler; using allocator_type = typename core::allocator_type; using node_type = typename core::node_type; using node_pointer = typename core::node_pointer; private: inline auto _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->_n + p : p; } size_type _n = 0; node_pointer _root = node_handler::nil; public: ~dynamic_segment_tree() { this->dispose(this->_root); } dynamic_segment_tree(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : core(allocator) {}; dynamic_segment_tree(const dynamic_segment_tree& source, const allocator_type& allocator) noexcept(NO_EXCEPT) : core(allocator), _n(source._n), _root(source._root) {} dynamic_segment_tree(dynamic_segment_tree&& source, const allocator_type& allocator) noexcept(NO_EXCEPT) : core(allocator), _n(source._n), _root(source._root) {} explicit dynamic_segment_tree(const size_type n, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : core(allocator), _n(n) {} template<std::convertible_to<value_type> T> dynamic_segment_tree(const std::initializer_list<T>& init_list, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_segment_tree(init_list, allocator) {} template<std::input_iterator I, std::sized_sentinel_for<I> S> dynamic_segment_tree(I first, S last, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_segment_tree(allocator) { this->assign(first, last); } template<std::ranges::input_range R> requires (!std::same_as<std::remove_cvref_t<R>, dynamic_segment_tree>) dynamic_segment_tree(R&& range, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_segment_tree(ALL(range), allocator) {} inline auto clone() const noexcept(NO_EXCEPT) { return *this; } inline auto size() const noexcept(NO_EXCEPT) { return this->_n; } inline auto& clear() noexcept(NO_EXCEPT) { this->dispose(this->_root); this->_n = 0; this->_root = node_handler::nil; return *this; } template<std::convertible_to<value_type> T> inline auto& assign(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) { return this->assign(init_list); } template<std::input_iterator I, std::sized_sentinel_for<I> S> inline auto& assign(I first, S last) noexcept(NO_EXCEPT) { this->_n = std::ranges::distance(first, last); this->_root = this->build(first, last); return *this; } template<std::ranges::input_range R> inline auto& assign(R&& range) noexcept(NO_EXCEPT) { return this->assign(ALL(range)); } inline auto& set(const size_type pos, value_type val) noexcept(NO_EXCEPT) { assert(pos < this->_n); this->core::set(this->_root, 0, this->_n, pos, val); return *this; } inline auto get(const size_type pos) const noexcept(NO_EXCEPT) { assert(pos < this->_n); return this->core::get(this->_root, 0, this->_n, pos); } inline auto& add(const size_type pos, const value_type& val) noexcept(NO_EXCEPT) { assert(0 <= pos && pos < this->_n); this->set(pos, this->get(pos) + val); return *this; } inline auto fold(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { assert(0 <= l && l <= r && r <= this->_n); return this->core::fold(this->_root, 0, this->_n, l, r); } inline auto fold() const noexcept(NO_EXCEPT) { return this->_root->acc; } inline auto& clear(const size_type l, const size_type r) noexcept(NO_EXCEPT) { assert(0 <= l && l <= r && r <= this->_n); this->core::clear(this->_root, 0, this->_n, l, r); return *this; } template<bool (*f)(value_type)> inline auto max_right(const size_type l) const noexcept(NO_EXCEPT) { return this->max_right(l, [](const value_type& val) { return f(val); }); } template<class F> inline auto max_right(const size_type l, const F &f) const noexcept(NO_EXCEPT) { assert(0 <= l && l <= this->_n); value_type acc; assert(f(acc)); const auto res = this->core::max_right(this->_root, 0, this->_n, l, f, acc); return res == -1 ? this->_n : res; } template<bool (*f)(value_type)> inline auto min_left(const size_type r) const noexcept(NO_EXCEPT) { return this->min_left(r, [](const value_type& val) noexcept(NO_EXCEPT) { return f(val); }); } template<class F> inline auto min_left(const size_type r, const F &f) const noexcept(NO_EXCEPT) { assert(0 <= r && r <= this->_n); value_type acc; assert(f(acc)); return this->core::min_left(this->_root, 0, this->_n, r, f, acc); } struct point_reference : internal::point_reference<dynamic_segment_tree> { point_reference(dynamic_segment_tree *const super, const size_type p) noexcept(NO_EXCEPT) : internal::point_reference<dynamic_segment_tree>(super, super->_positivize_index(p)) { assert(0 <= this->_pos && this->_pos < this->_super->_n); } inline operator value_type() const noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } inline auto val() const noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } inline auto& operator=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->set(this->_pos, v); return *this; } inline auto& operator+=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->add(this->_pos, v); return *this; } }; struct range_reference : internal::range_reference<dynamic_segment_tree> { range_reference(dynamic_segment_tree *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<dynamic_segment_tree>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->_n); } inline auto fold() noexcept(NO_EXCEPT) { return this->_super->fold(this->_begin, this->_end); } }; inline auto operator[](const size_type p) noexcept(NO_EXCEPT) { return point_reference(this, p); } inline auto operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return range_reference(this, l, r); } public: struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, const dynamic_segment_tree, iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, this->_n); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } using core::dump_rich; using core::_debug; debugger::debug_t dump_rich(const std::string prefix = " ") const { return "\n" + this->dump_rich(this->_root, prefix); } debugger::debug_t _debug() const { return "[ " + this->_debug(this->_root) + " ]"; } }; template<class Action, class Allocator = std::allocator<Action>> using persistent_dynamic_segment_tree = dynamic_segment_tree<Action, node_handlers::cloneable<Allocator>>; namespace pmr { template<class Action> using dynamic_segment_tree = uni::dynamic_segment_tree<Action, std::pmr::polymorphic_allocator<Action>>; template<class Action> using persistent_dynamic_segment_tree = uni::persistent_dynamic_segment_tree<Action, std::pmr::polymorphic_allocator<Action>>; }; // namespace pmr } // namespace uni #line 2 "data_structure/dynamic_sequence.hpp" #line 12 "data_structure/dynamic_sequence.hpp" #line 15 "data_structure/dynamic_sequence.hpp" #line 2 "internal/uncopyable.hpp" namespace uni { namespace internal { struct uncopyable { uncopyable() noexcept {} uncopyable(const uncopyable&) = delete; uncopyable& operator=(const uncopyable&) = delete; }; } // namespace internal } // namespace uni #line 22 "data_structure/dynamic_sequence.hpp" #line 25 "data_structure/dynamic_sequence.hpp" #line 27 "data_structure/dynamic_sequence.hpp" #line 2 "data_structure/internal/basic_tree_concept.hpp" #line 6 "data_structure/internal/basic_tree_concept.hpp" #line 8 "data_structure/internal/basic_tree_concept.hpp" namespace uni { namespace internal { template<class T> concept basic_tree = std::default_initializable<T> && std::integral<typename T::size_type> && requires (T base, typename T::size_type key, typename T::node_pointer tree, const typename T::node_pointer const_tree) { base.split(const_tree, key, tree, tree); base.merge(tree, const_tree, const_tree); }; } // namespace internal } // namespace name #line 2 "data_structure/internal/tree_dumper.hpp" #line 5 "data_structure/internal/tree_dumper.hpp" #line 9 "data_structure/internal/tree_dumper.hpp" namespace uni { namespace internal { template<class Derived, class Core, bool LEAF_ONLY> struct dumpable_tree { private: using node_handler = Core::node_handler; using node_pointer = Core::node_pointer; using size_type = Core::size_type; inline auto _push(const node_pointer& tree) { return static_cast<Derived*>(this)->_impl.push(tree); // return static_cast<Derived*>(this)->push(tree); } public: debugger::debug_t dump_rich(node_pointer tree, const std::string prefix, const int dir, size_type& index) requires (!LEAF_ONLY) { if(!tree || tree == node_handler::nil) return prefix + "\n"; this->_push(tree); // debug(tree->priority >= tree->left->priority, tree->priority, tree->left->priority); // debug(tree->priority >= tree->right->priority, tree->priority, tree->right->priority); assert(tree->priority >= tree->left->priority); assert(tree->priority >= tree->right->priority); const auto left = this->dump_rich(tree->left, prefix + (dir == 1 ? "| " : " "), -1, index); const auto here = prefix + "--+ [" + debugger::dump(index) + ", " + debugger::dump(index + tree->length) + ") : " + "<" + debugger::dump(tree->priority) + "> " + debugger::dump(tree->data) + " [" + debugger::dump(tree->length) + "]\n"; index += tree->length; const auto right = this->dump_rich(tree->right, prefix + (dir == -1 ? "| " : " "), 1, index); return left + here + right; } debugger::debug_t dump_rich(node_pointer tree, const std::string prefix, const int dir, size_type& index) requires ( LEAF_ONLY && requires { typename Core::node_colors; } ) { if(!tree || tree == node_handler::nil) return prefix + "\n"; this->_push(tree); const auto left = this->dump_rich(tree->left, prefix + (dir == 1 ? "| " : " "), -1, index); const auto right = this->dump_rich(tree->right, prefix + (dir == -1 ? "| " : " "), 1, index); const auto color = tree->color == Core::node_colors::BLACK ? "<->" : "<+>"; const auto here = [&]() -> std::string { if(tree->is_leaf()) { index += tree->size; return prefix + "--+ [" + debugger::dump(index - tree->size) + ", " + debugger::dump(index) + ") : " + debugger::COLOR_STRING + color + debugger::COLOR_INIT + " " + debugger::dump(tree->data) + " [" + debugger::dump(tree->size) + "]\n"; } return ""; }(); return left + here + right; } inline debugger::debug_t dump_rich(const node_pointer& tree, const std::string prefix = " ", const int dir = 0) { size_type index = 0; return this->dump_rich(tree, prefix, dir, index); } debugger::debug_t _debug(node_pointer tree) requires (!LEAF_ONLY) { if(!tree || tree == node_handler::nil) return ""; this->_push(tree); return "(" + this->_debug(tree->left) + " " + debugger::dump(tree->data) + " [" + debugger::dump(tree->length) + "] " + this->_debug(tree->right) + ")"; } debugger::debug_t _debug(node_pointer tree) requires LEAF_ONLY { if(!tree || tree == node_handler::nil) return ""; this->_push(tree); return "(" + this->_debug(tree->left) + " " + ( tree->is_leaf() ? debugger::dump(tree->data) + " [" + debugger::dump(tree->size) + "] " : "" ) + this->_debug(tree->right) + ")"; } }; } // namespace internal } // namespace uni #line 2 "data_structure/internal/dynamic_tree.hpp" #line 6 "data_structure/internal/dynamic_tree.hpp" #line 9 "data_structure/internal/dynamic_tree.hpp" #line 12 "data_structure/internal/dynamic_tree.hpp" #line 15 "data_structure/internal/dynamic_tree.hpp" #line 17 "data_structure/internal/dynamic_tree.hpp" namespace uni { namespace internal { namespace dynamic_tree_impl { namespace internal { template<class T> consteval auto to_val() { if constexpr(actions::internal::operatable_action<T>) return typename T::operand{}; else return T{}; } template<class T> consteval auto to_acc() { if constexpr(actions::internal::operatable_action<T>) return typename T::operand{}; else return dummy{}; } template<class T> consteval auto to_lazy() { if constexpr(actions::internal::effective_action<T>) return typename T::operation{}; else return dummy{}; } template<class T, bool LEAF_ONLY, bool MAY_BE_LAZY = true> struct data_type { using val_t = decltype(to_val<T>()); using acc_t = decltype(to_acc<T>()); using lazy_t = decltype(to_lazy<T>()); val_t val; [[no_unique_address]] acc_t acc; [[no_unique_address]] std::conditional_t<MAY_BE_LAZY, lazy_t, dummy> lazy; bool rev = false; data_type() noexcept = default; data_type(const val_t& _val) noexcept(NO_EXCEPT) : val(_val) {} auto _debug() const { return this->val; } friend bool operator==(const data_type& lhs, const data_type& rhs) noexcept(NO_EXCEPT) { return lhs.val == rhs.val; } friend auto operator<=>(const data_type& lhs, const data_type& rhs) noexcept(NO_EXCEPT) { return lhs.val <=> rhs.val; } }; template<class ActionOrValue, class Derived, class Context> struct basic_core : Context::substance<Derived, internal::data_type<ActionOrValue, Context::LEAF_ONLY>> { using data_type = internal::data_type<ActionOrValue, Context::LEAF_ONLY>; private: using base = typename Context::substance<Derived, data_type>; static_assert(basic_tree<base>); public: using base::base; using node_handler = typename base::node_handler; using node_pointer = typename base::node_pointer; using size_type = typename base::size_type; using operand = data_type::val_t; using operation = data_type::lazy_t; inline auto val(const node_pointer& node) const noexcept(NO_EXCEPT) { if constexpr(Context::LEAF_ONLY) { if(node->is_leaf()) return node->size * node->data.val; return node->data.val; } else { return node->data.acc; } } using base::split; using base::merge; inline void split(const node_pointer tree, const size_type l, const size_type r, node_pointer& t0, node_pointer& t1, node_pointer& t2) noexcept(NO_EXCEPT) { // See: https://twitter.com/KakurenboUni/status/1784576244321018209 this->split(tree, l, t0, t1); this->split(t1, r - l, t1, t2); } inline void split( const node_pointer tree, const size_type l, const size_type m, const size_type r, node_pointer& t0, node_pointer& t1, node_pointer& t2, node_pointer& t3 ) noexcept(NO_EXCEPT) { // See: https://twitter.com/KakurenboUni/status/1784576244321018209 this->split(tree, l, m, t0, t1, t2); this->split(t2, r - m, t2, t3); } inline void merge(node_pointer& tree, node_pointer t0, const node_pointer t1, const node_pointer t2) noexcept(NO_EXCEPT) { this->merge(t0, t0, t1); this->merge(tree, t0, t2); } void erase(node_pointer& tree, const size_type l, const size_type r) noexcept(NO_EXCEPT) { assert(l <= r); node_pointer t0, t1, t2; this->split(tree, l, r, t0, t1, t2); this->dispose(t1); this->merge(tree, t0, t2); } auto pop(node_pointer& tree, const size_type pos, const size_type count = 1) noexcept(NO_EXCEPT) { assert(0 <= count); if(count == 0) return operand{}; node_pointer t0, t1, t2; this->split(tree, pos, pos + count, t0, t1, t2); const auto res = this->val(t1); this->dispose(t1); this->merge(tree, t0, t2); return res; } operand get(node_pointer tree, const size_type pos) noexcept(NO_EXCEPT) { if(tree == node_handler::nil || pos < 0 || pos >= tree->size) return {}; this->base::push(tree); const auto lower_bound = tree->left->size; const auto upper_bound = tree->size - tree->right->size; if(pos < lower_bound) { return this->get(tree->left, pos); } else if(pos >= upper_bound) { return this->get(tree->right, pos - upper_bound); } else { return tree->data.val; } } template<std::forward_iterator I> requires std::output_iterator<I, operand> void enumerate(node_pointer tree, I& itr) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return; this->base::push(tree); this->enumerate(tree->left, itr); if constexpr(Context::LEAF_ONLY) { if(tree->is_leaf()) { REP(tree->size) *(itr++) = tree->data.val; } } else { REP(tree->length) *(itr++) = tree->data.val; } this->enumerate(tree->right, itr); } auto fold(node_pointer& tree, size_type l, size_type r) noexcept(NO_EXCEPT) { assert(l <= r); if(l == r) return operand{}; node_pointer t0, t1, t2; this->split(tree, l, r, t0, t1, t2); const operand res = this->val(t1); this->merge(tree, t0, t1, t2); return res; } }; } // namespace internal } // namespace dynamic_tree_impl } // namespace internal } // namespace uni #line 31 "data_structure/dynamic_sequence.hpp" #line 2 "data_structure/treap.hpp" #line 13 "data_structure/treap.hpp" #line 17 "data_structure/treap.hpp" #line 23 "data_structure/treap.hpp" #line 25 "data_structure/treap.hpp" #line 27 "data_structure/treap.hpp" #line 29 "data_structure/treap.hpp" #line 32 "data_structure/treap.hpp" namespace uni { namespace internal { // Thanks to: https://github.com/xuzijian629/library2/blob/master/treap/implicit_treap.cpp template<class Allocator, class Derived, std::integral SizeType, class ValueType, i64 Id> struct treap_impl : private uncopyable { using size_type = SizeType; using value_type = ValueType; struct node_type; using node_handler = typename uni::node_handlers::reusing<Allocator>::template handler<node_type>; using allocator_type = typename node_handler::allocator_type; using node_pointer = typename node_handler::node_pointer; private: using derived = Derived; inline auto* _derived() noexcept(NO_EXCEPT) { return static_cast<derived*>(this); } inline const auto* _derived() const noexcept(NO_EXCEPT) { return static_cast<const derived*>(this); } [[no_unique_address]] node_handler _node_handler; static inline random_engine_32bit _rand; using priority_type = random_engine_32bit::result_type; public: void pull(const node_pointer tree) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return; tree->size = tree->left->size + tree->length + tree->right->size; this->_derived()->pull(tree); } void push(const node_pointer tree) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return; this->_derived()->push(tree); } node_pointer create(const value_type& val, const size_type size) noexcept(NO_EXCEPT) { if(size == 0) return node_handler::nil; return this->_node_handler.create(val, size); } void dispose(node_pointer tree) noexcept(NO_EXCEPT) { if(this->_node_handler.disposable(tree)) { this->dispose(tree->left); this->dispose(tree->right); this->_node_handler.dispose(tree); } } template<class... Args> inline void constexpr clone(Args&&...) const noexcept {} private: void _rotate_right(node_pointer& tree) noexcept(NO_EXCEPT) { // push ommitted auto t = tree->left; tree->left = t->right; this->pull(tree); t->right = tree; this->pull(t); tree = std::move(t); } void _rectify(const node_pointer tree) const noexcept(NO_EXCEPT) { if(tree->size == 0) return; std::vector<priority_type> priorities(tree->size); std::ranges::generate(priorities, treap_impl::_rand); std::ranges::make_heap(priorities); std::queue<node_pointer> queue; queue.push(tree); auto itr = std::ranges::begin(priorities); while(!queue.empty()) { node_pointer node = queue.front(); queue.pop(); node->priority = *(itr++); if(node->left != node_handler::nil) queue.push(node->left); if(node->right != node_handler::nil) queue.push(node->right); } } template<std::random_access_iterator I, std::sized_sentinel_for<I> S> requires std::constructible_from<value_type, std::iter_value_t<I>> node_pointer _build(I first, S last) noexcept(NO_EXCEPT) { if(first == last) return node_handler::nil; const auto length = std::ranges::distance(first, last); const auto middle = std::ranges::next(first, length >> 1); node_pointer tree = this->create(value_type{ *middle }, 1); tree->left = this->_build(first, middle); tree->right = this->_build(std::ranges::next(middle), last); this->pull(tree); return tree; } template<std::random_access_iterator I, std::sized_sentinel_for<I> S> requires std::constructible_from<value_type, typename std::iter_value_t<I>::first_type> && std::integral<typename std::iter_value_t<I>::second_type> node_pointer _build(I first, S last) noexcept(NO_EXCEPT) { if(first == last) return node_handler::nil; const auto length = std::ranges::distance(first, last); const auto middle = std::ranges::next(first, length >> 1); node_pointer tree = this->create(value_type{ middle->first }, middle->second ); tree->left = this->_build(first, middle); tree->right = this->_build(std::ranges::next(middle), last); this->pull(tree); return tree; } void _split(node_pointer tree, const size_type pos, node_pointer& left, node_pointer& right) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) { left = right = node_handler::nil; return; } this->push(tree); const auto lower_bound = tree->left->size; const auto upper_bound = tree->size - tree->right->size; if(pos <= lower_bound) { node_pointer t; this->split(tree->left, pos, left, t); tree->left = t; if(tree->priority < t->priority) this->_rotate_right(tree); right = std::move(tree); this->pull(right); } else if(pos >= upper_bound) { this->split(tree->right, pos - upper_bound, tree->right, right); left = std::move(tree); this->pull(left); } else { tree->length = pos - lower_bound; this->merge(tree->right, this->create(tree->data, upper_bound - pos), tree->right); this->split(tree->right, 0, tree->right, right), left = std::move(tree); this->pull(left); } } public: explicit treap_impl(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _node_handler(allocator) {} template<std::random_access_iterator I, std::sized_sentinel_for<I> S> node_pointer build(I first, S last) { const auto tree = this->_build(first, last); this->_rectify(tree); return tree; } struct node_type { priority_type priority = std::numeric_limits<priority_type>::lowest(); node_pointer left = node_handler::nil, right = node_handler::nil; size_type length, size; [[no_unique_address]] value_type data; node_type() noexcept = default; node_type(const value_type& _data, const size_type _size) noexcept(NO_EXCEPT) : priority(treap_impl::_rand()), length(_size), size(_size), data(_data) {} }; template<bool STRICT = false, bool RETURN_EXISTENCE = false> void split(const node_pointer tree, const value_type& val, node_pointer& left, node_pointer& right, bool* exist = nullptr) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) { left = right = node_handler::nil; return; } this->push(tree); if constexpr(RETURN_EXISTENCE) *exist |= val == tree->data; if(val < tree->data || (!STRICT && val == tree->data)) { this->template split<STRICT, RETURN_EXISTENCE>(tree->left, val, left, tree->left, exist); right = std::move(tree); this->pull(right); } else { this->template split<STRICT, RETURN_EXISTENCE>(tree->right, val, tree->right, right, exist); left = std::move(tree); this->pull(left); } } void split(const node_pointer tree, const size_type pos, node_pointer& left, node_pointer& right) noexcept(NO_EXCEPT) { if(pos <= 0) { left = node_handler::nil; this->merge(right, this->create(value_type{}, -pos), std::move(tree)); } else if(tree->size <= pos) { right = node_handler::nil; this->merge(left, std::move(tree), this->create(value_type{}, pos - tree->size)); } else { this->_split(std::move(tree), pos, left, right); } } void merge(node_pointer& tree, const node_pointer left, const node_pointer right) noexcept(NO_EXCEPT) { this->push(left); this->push(right); if(left == node_handler::nil || right == node_handler::nil) { tree = left == node_handler::nil ? right : left; } else if(left->priority < right->priority) { this->merge(right->left, left, right->left), tree = std::move(right); } else { this->merge(left->right, left->right, right), tree = std::move(left); } this->pull(tree); } }; } // namespace internal template<std::integral SizeType = i64, class Allocator = std::allocator<SizeType>, i64 Id = -1> struct treap_context { static constexpr bool LEAF_ONLY = false; template<class Derived, class ValueType = internal::dummy> using substance = internal::treap_impl<Allocator, Derived, SizeType, ValueType, Id>; }; namespace pmr { template<std::integral SizeType = i64, i64 Id = -1> using treap_context = uni::treap_context<SizeType, std::pmr::polymorphic_allocator<SizeType>, Id>; } // namespace pmr } // namespace uni #line 33 "data_structure/dynamic_sequence.hpp" #line 35 "data_structure/dynamic_sequence.hpp" #line 38 "data_structure/dynamic_sequence.hpp" #line 40 "data_structure/dynamic_sequence.hpp" namespace uni { namespace internal { namespace dynamic_tree_impl { template<class ActionOrValue, class Context> struct sequence_core : internal::basic_core<ActionOrValue, sequence_core<ActionOrValue, Context>, Context> // , // dumpable_tree< // sequence_core<ActionOrValue, Context>, // internal::basic_core<ActionOrValue, sequence_core<ActionOrValue, Context>, Context>, // Context::LEAF_ONLY // > { private: using base = typename internal::basic_core<ActionOrValue, sequence_core, Context>; public: static constexpr bool ACC = actions::internal::operatable_action<ActionOrValue>; static constexpr bool LAZY = actions::internal::effective_action<ActionOrValue>; using base::base; using data_type = base::data_type; using operand = base::operand; using operation = base::operation; using node_handler = typename base::node_handler; using node_type = typename base::node_type; using node_pointer = typename base::node_pointer; using size_type = typename base::size_type; inline void pull(const node_pointer& tree) const noexcept(NO_EXCEPT) { if constexpr(ACC) { if constexpr(Context::LEAF_ONLY) { tree->data.val = this->val(tree->left) + this->val(tree->right); } else { tree->data.acc = tree->left->data.acc + tree->length * tree->data.val + tree->right->data.acc; } } } inline void push(const node_pointer& tree) noexcept(NO_EXCEPT) { if(tree->data.rev) { tree->data.rev = false; std::swap(tree->left, tree->right); if(tree->left != node_handler::nil) { this->clone(tree->left); tree->left->data.rev ^= 1; } if(tree->right != node_handler::nil) { this->clone(tree->right); tree->right->data.rev ^= 1; } } if constexpr(LAZY) { if(tree->data.lazy != operation{}) { if constexpr(Context::LEAF_ONLY) { if(tree->left != node_handler::nil) { this->clone(tree->left); if(tree->left->is_leaf()) { tree->left->data.val = ActionOrValue::mapping(tree->data.lazy, tree->left->data.val); } else { tree->left->data.lazy = tree->data.lazy + tree->left->data.lazy; tree->left->data.val = ActionOrValue::mapping(ActionOrValue::power(tree->data.lazy, tree->left->size), tree->left->data.val); } } if(tree->right != node_handler::nil) { this->clone(tree->right); if(tree->right->is_leaf()) { tree->right->data.val = ActionOrValue::mapping(tree->data.lazy, tree->right->data.val); } else { tree->right->data.lazy = tree->data.lazy + tree->right->data.lazy; tree->right->data.val = ActionOrValue::mapping(ActionOrValue::power(tree->data.lazy, tree->right->size), tree->right->data.val); } } } else { if(tree->left != node_handler::nil) { tree->left->data.lazy = tree->data.lazy + tree->left->data.lazy; tree->left->data.acc = ActionOrValue::mapping(ActionOrValue::power(tree->data.lazy, tree->left->size), tree->left->data.acc); } if(tree->right != node_handler::nil) { tree->right->data.lazy = tree->data.lazy + tree->right->data.lazy; tree->right->data.acc = ActionOrValue::mapping(ActionOrValue::power(tree->data.lazy, tree->right->size), tree->right->data.acc); } } tree->data.val = ActionOrValue::mapping(tree->data.lazy, tree->data.val); tree->data.lazy = operation{}; } } } inline void update(node_pointer& tree) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return; this->base::push(tree); this->base::pull(tree); } void insert(node_pointer& tree, const size_type pos, const operand& val, const size_type count = 1) noexcept(NO_EXCEPT) { assert(count >= 0); if(count == 0) return; node_pointer t0, t1; this->split(tree, pos, t0, t1); this->merge(tree, t0, this->create(val, count), t1); } template<std::input_iterator I, std::sized_sentinel_for<I> S> void insert(node_pointer& tree, const size_type pos, I first, S last) noexcept(NO_EXCEPT) { node_pointer t0, t1; this->split(tree, pos, t0, t1); this->merge(tree, t0, this->build(first, last), t1); } void add(node_pointer& tree, const size_type pos, const operand& val) noexcept(NO_EXCEPT) { node_pointer t0, t1, t2; this->split(tree, pos, t0, t1); this->split(t1, 1, t1, t2); const auto prev = this->val(t1); this->dispose(t1); t1 = this->create(data_type{ prev + val }, 1); this->merge(tree, t0, t1, t2); } void fill(node_pointer& tree, const size_type l, const size_type r, const operand& val) noexcept(NO_EXCEPT) { assert(l <= r); if(l == r) return; node_pointer t0, t1, t2; this->split(tree, l, r, t0, t1, t2); // this->split(tree, l, r, t0, t1, t2); // this->split(tree, l, t0, t1); // debug(this->dump_rich(t0), this->dump_rich(t1)); // this->split(t1, r - l, t1, t2); // debug(this->dump_rich(t1), this->dump_rich(t2)); this->dispose(t1); t1 = this->create(val, r - l); this->merge(tree, t0, t1, t2); // this->merge(t0, t0, t1); // debug(this->dump_rich(t0)); // this->merge(tree, t0, t2); // debug(this->dump_rich(tree)); } template<std::input_iterator I, std::sized_sentinel_for<I> S> void fill(node_pointer& tree, const size_type pos, I first, S last) noexcept(NO_EXCEPT) { node_pointer t0, t1, t2; this->split(tree, pos, pos + std::ranges::distance(first, last), t0, t1, t2); this->dispose(t1); this->merge(tree, t0, this->build(first, last), t2); } void apply(node_pointer& tree, const size_type l, const size_type r, const operation& val) noexcept(NO_EXCEPT) requires LAZY { assert(l <= r); if(l == r) return; node_pointer t0, t1, t2; this->split(tree, l, r, t0, t1, t2); if(t1 == node_handler::nil) t1 = this->create(data_type{}, r - l); t1->data.lazy = val + t1->data.lazy; this->merge(tree, t0, t1, t2); } void reverse(node_pointer& tree, const size_type l, const size_type r) noexcept(NO_EXCEPT) { assert(l <= r); if(l == r) return; node_pointer t0, t1, t2; this->split(tree, l, r, t0, t1, t2); if(t1 != node_handler::nil) t1->data.rev ^= 1; this->merge(tree, t0, t1, t2); } void shift_left(node_pointer& tree, const size_type l, const size_type r, const size_type count = 1) noexcept(NO_EXCEPT) { assert(l <= r); if(count < 0) return this->shift_right(tree, l, r, -count); if(count == 0) return; if(count >= r - l) return this->fill(tree, l, r, {}); node_pointer t0, t1, t2, t3; this->split(tree, l, l + count, r, t0, t1, t2, t3); this->dispose(t1); this->merge(t2, t2, this->create({}, count)); this->merge(tree, t0, t2, t3); } void shift_right(node_pointer& tree, const size_type l, const size_type r, const size_type count = 1) noexcept(NO_EXCEPT) { assert(l <= r); if(count < 0) return this->shift_left(tree, l, r, -count); if(count == 0) return; if(count >= r - l) return this->fill(tree, l, r, {}); node_pointer t0, t1, t2, t3; this->split(tree, l, r - count, r, t0, t1, t2, t3); this->dispose(t2); this->merge(t1, this->create({}, count), t1); this->merge(tree, t0, t1, t3); } void rotate(node_pointer& tree, const size_type l, const size_type m, const size_type r) noexcept(NO_EXCEPT) { assert(l <= m && m < r); if(l == m) return; node_pointer t0, t1, t2, t3; this->split(tree, l, m, r, t0, t1, t2, t3); this->merge(t2, t2, t1); this->merge(tree, t0, t2, t3); } template<bool LEFT> size_type find(const node_pointer& tree, operand& val, const size_type offset) noexcept(NO_EXCEPT) { if(tree->data.acc + val == val) { return -1; } if constexpr(LEFT) { if(tree->left != node_handler::nil and tree->left->data.acc + val != val) { return this->find<true>(tree->left, val, offset); } else { return tree->data.val + val != val ? offset + tree->left->size : this->find<true>(tree->right, val, offset + tree->left->size + 1); } } else { if(tree->right != node_handler::nil and tree->right->data.acc + val != val) { return this->find<false>(tree->right, val, offset + tree->left->size + 1); } else { return tree->data.val + val != val ? offset + tree->left->size : this->find<false>(tree->left, val, offset); } } } template<bool LEFT> inline size_type find(node_pointer& tree, const size_type l, const size_type r, const operand& val) noexcept(NO_EXCEPT) { if(l == r) return -1; node_pointer t0, t1, t2; this->split(tree, l, r, t0, t1, t2); const size_type res = this->find<LEFT>(t1, val, l); this->merge(tree, t0, t1, t2); return res; } }; } // namespace dynamic_tree_impl } // namespace internal template<class ActionOrValue, class Context = treap_context<>> requires internal::available_with<internal::dynamic_tree_impl::sequence_core, ActionOrValue, Context> struct dynamic_sequence : private internal::dumpable_tree< dynamic_sequence<ActionOrValue, Context>, internal::dynamic_tree_impl::sequence_core<ActionOrValue, Context>, Context::LEAF_ONLY > { private: using sequence_core = internal::dynamic_tree_impl::sequence_core<ActionOrValue, Context>; template<class T> static consteval auto _to_operator() { if constexpr(requires { typename T::value_type; }) return typename T::value_type{}; else return T{}; } public: using operand = typename sequence_core::operand; using operation = typename sequence_core::operation; using value_type = operand; using operator_type = decltype(_to_operator<operation>()); using node_handler = typename sequence_core::node_handler; using allocator_type = typename sequence_core::allocator_type; using node_type = typename sequence_core::node_type; using node_pointer = typename sequence_core::node_pointer; using size_type = typename sequence_core::size_type; private: using dumper = internal::dumpable_tree<dynamic_sequence, sequence_core, Context::LEAF_ONLY>; friend dumper; sequence_core _impl; node_pointer _root = node_handler::nil; size_type _offset = 0; template<std::same_as<size_type>... SizeTypes> inline void _normalize_index(SizeTypes&... indices) noexcept(NO_EXCEPT) { const auto min_index = std::min({ indices... }); ((indices -= this->_offset), ...); if(min_index < this->_offset) this->_offset = min_index; } public: ~dynamic_sequence() { this->_impl.dispose(this->_root); } dynamic_sequence(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator) {}; dynamic_sequence(const node_pointer& root, const size_type offset = 0, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator), _root(root), _offset(offset) {}; template<std::input_iterator I, std::sized_sentinel_for<I> S> dynamic_sequence(I first, S last, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator) { this->assign(first, last); } explicit dynamic_sequence(const size_type size, const value_type& val, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator) { this->assign(size, val); } explicit dynamic_sequence(const size_type size, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_sequence(size, value_type{}, allocator) {} template<std::ranges::input_range R> requires (!std::same_as<std::remove_cvref_t<R>, dynamic_sequence>) explicit dynamic_sequence(R&& range, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_sequence(ALL(range), allocator) {} template<std::convertible_to<value_type> T> dynamic_sequence(const std::initializer_list<T>& values, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_sequence(values, allocator) {} inline auto offset() const noexcept(NO_EXCEPT) { return this->_offset; } inline auto& root() noexcept(NO_EXCEPT) { return this->_root; } inline const auto& root() const noexcept(NO_EXCEPT) { return this->_root; } inline auto size() const noexcept(NO_EXCEPT) { return this->_root->size; } inline bool empty() const noexcept(NO_EXCEPT) { return this->size() == 0; } template<internal::resizable_range Container> inline auto to() noexcept(NO_EXCEPT) { Container res; res.resize(this->size()); auto itr = std::ranges::begin(res); this->_impl.enumerate(this->_root, itr); return res; } inline void clear() noexcept(NO_EXCEPT) { this->_impl.dispose(this->_root); this->_root = node_handler::nil; this->_offset = 0; } inline auto clone() const noexcept { return *this; } inline auto clone(size_type l, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); node_pointer t0, t1, t2; this->_impl.split(this->_root, l, r, t0, t1, t2); this->_impl.merge(this->_root, t0, t1, t2); return dynamic_sequence(t1, this->_offset); } inline auto split(size_type pos) noexcept(NO_EXCEPT) { this->_normalize_index(pos); node_pointer t0, t1; this->_impl.split(this->_root, pos, t0, t1); return std::make_pair(dynamic_sequence(t0, this->_offset), dynamic_sequence(t1, this->_offset)); } inline auto extract(size_type l, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); node_pointer t0, t1, t2; this->_impl.split(this->_root, l, r, t0, t1, t2); this->_impl.merge(this->_root, t0, t2); return dynamic_sequence(t1, this->_offset); } inline auto& insert(size_type pos, const dynamic_sequence& other) noexcept(NO_EXCEPT) { this->_normalize_index(pos); node_pointer t0, t1; this->_impl.split(this->_root, pos, t0, t1); this->_impl.merge(this->_root, t0, other._root, t1); return *this; } inline auto& replace(size_type l, size_type r, const dynamic_sequence& other) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); node_pointer t0, t1, t2; this->_impl.split(this->_root, l, r, t0, t1, t2); this->_impl.merge(this->_root, t0, other._root, t2); return *this; } inline auto& merge(const dynamic_sequence& other) noexcept(NO_EXCEPT) { this->_impl.merge(this->_root, this->_root, other._root); return *this; } template<std::input_iterator I, std::sized_sentinel_for<I> S> inline auto& assign(I first, S last) noexcept(NO_EXCEPT) { this->clear(); this->_root = this->_impl.build(first, last); return *this; } inline auto& assign(const size_type size, const value_type& val = value_type{}) noexcept(NO_EXCEPT) { this->clear(); this->_impl.insert(this->_root, 0, val, size); return *this; } template<std::ranges::input_range R> inline auto& assign(R&& range) noexcept(NO_EXCEPT) { return this->assign(ALL(range)); } template<std::convertible_to<value_type> T> inline auto& assign(const std::initializer_list<T>& values) noexcept(NO_EXCEPT) { return this->assign(values); } inline auto& resize(const size_type size, const value_type& val = value_type{}) noexcept(NO_EXCEPT) { if(this->size() > size) this->_impl.erase(this->_root, size, this->size()); if(this->size() < size) this->push_back(val, size - this->size()); return *this; } inline auto& expand(size_type l, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); node_pointer t0, t1, t2; this->_impl.split(this->_root, l, r, t0, t1, t2); this->_impl.merge(this->_root, t0, t1, t2); return *this; } inline auto& expand(size_type pos) noexcept(NO_EXCEPT) { this->_normalize_index(pos); node_pointer t0, t1; this->_impl.split(this->_root, pos, t0, t1); this->_impl.merge(this->_root, t0, t1); return *this; } inline auto& fill(const value_type& val) noexcept(NO_EXCEPT) { this->_impl.fill(this->_root, 0, this->size(), val); return *this; } inline auto fold() noexcept(NO_EXCEPT) { return this->_impl.val(this->_root); } inline auto& apply(const operator_type& val) noexcept(NO_EXCEPT) { this->_root->data.lazy = this->_root->data.lazy + val; this->update(this->_root); return *this; } inline auto front() noexcept(NO_EXCEPT) { return this->_impl.fold(this->_root, 0, 1); } inline auto back() noexcept(NO_EXCEPT) { return this->_impl.fold(this->_root, this->size() - 1, this->size()); } inline auto& push_front(const value_type& val, const size_type count = 1) noexcept(NO_EXCEPT) { this->_impl.insert(this->_root, 0, val, count); return *this; } inline auto& push_back(const value_type& val, const size_type count = 1) noexcept(NO_EXCEPT) { this->_impl.insert(this->_root, this->size(), val, count); return *this; } inline auto& reverse() noexcept(NO_EXCEPT) { this->_root->data.rev ^= 1; this->_impl.update(this->_root); return *this; } inline auto& shift_left(const size_type count = 1) noexcept(NO_EXCEPT) { this->_impl.shift_left(this->_root, 0, this->size(), count); return *this; } inline auto& shift_right(const size_type count = 1) noexcept(NO_EXCEPT) { this->_impl.shift_right(this->_root, 0, this->size(), count); return *this; } // Same usage as: std::rotate(:m:) inline auto& rotate(size_type m) noexcept(NO_EXCEPT) { this->_normalize_index(m); this->_impl.rotate(this->_root, 0, m, this->size()); return *this; } // Same usage as: std::rotate(:m:) inline auto& rotate_left(const size_type count = 1) noexcept(NO_EXCEPT) { assert(!this->empty()); this->_impl.rotate(this->_root, 0, uni::mod(count, this->size()), this->size()); return *this; } // Same usage as: std::rotate(:m:) inline auto& rotate_right(const size_type count = 1) noexcept(NO_EXCEPT) { assert(!this->empty()); this->_impl.rotate(this->_root, 0, uni::mod(-count, this->size()), this->size()); return *this; } template<std::input_iterator I, std::sized_sentinel_for<I> S> inline auto& insert(size_type pos, I first, S last) noexcept(NO_EXCEPT) { this->_normalize_index(pos); this->_impl.insert(this->_root, pos, first, last); return *this; } inline auto& insert(size_type pos, const operand& val, const size_type count = 1) noexcept(NO_EXCEPT) { this->_normalize_index(pos); this->_impl.insert(this->_root, pos, val, count); return *this; } inline auto& erase(size_type l, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); this->_impl.erase(this->_root, l, r); return *this; } inline auto& erase(const size_type pos) noexcept(NO_EXCEPT) { return this->erase(pos, pos + 1); } inline auto pop(size_type pos, const size_type count = 1) noexcept(NO_EXCEPT) { this->_normalize_index(pos); return this->_impl.pop(this->_root, pos, count); } inline auto get(size_type pos) noexcept(NO_EXCEPT) { this->_normalize_index(pos); return this->_impl.get(this->_root, pos); } inline auto& add(size_type pos, const value_type& val) noexcept(NO_EXCEPT) { this->_normalize_index(pos); this->_impl.add(this->_root, pos, val); return *this; } inline auto& fill(size_type l, size_type r, const value_type& val) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); this->_impl.fill(this->_root, l, r, val); return *this; } inline auto fold(size_type l, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); return this->_impl.fold(this->_root, l, r); } inline auto& apply(size_type l, size_type r, const operation& val) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); this->_impl.apply(this->_root, l, r, val); return *this; } inline auto& reverse(size_type l, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); this->_impl.reverse(this->_root, l, r); return *this; } inline auto& rotate(size_type l, size_type m, size_type r) noexcept(NO_EXCEPT) { this->_normalize_index(l, m, r); this->_impl.rotate(this->_root, l, m, r); return *this; } inline auto& shift_left(size_type l, size_type r, const size_type count = 1) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); this->_impl.shift_left(this->_root, l, r, count); return *this; } inline auto& shift_right(size_type l, size_type r, const size_type count = 1) noexcept(NO_EXCEPT) { this->_normalize_index(l, r); this->_impl.shift_right(this->_root, l, r, count); return *this; } inline auto pop_front(const size_type count = 1) noexcept(NO_EXCEPT) { return this->_impl.pop(this->_root, 0, count); } inline auto pop_back(const size_type count = 1) noexcept(NO_EXCEPT) { return this->_impl.pop(this->_root, this->size() - count, count); } template<std::ranges::input_range R> requires (!std::same_as<std::remove_cvref_t<R>, dynamic_sequence>) inline auto& insert(const size_type pos, R&& range) noexcept(NO_EXCEPT) { return this->insert(pos, ALL(range)); } inline auto& set(const size_type pos, const value_type& val) noexcept(NO_EXCEPT) { return this->fill(pos, pos + 1, val); } inline auto& apply(const size_type pos, const operator_type& val) noexcept(NO_EXCEPT) { return this->apply(pos, pos + 1, val); } inline auto& rotate_left(const size_type l, const size_type r, const size_type count = 1) noexcept(NO_EXCEPT) { assert(l < r); return this->rotate(l, l + uni::mod(count, r - l), r); } inline auto& rotate_right(const size_type l, const size_type r, const size_type count = 1) noexcept(NO_EXCEPT) { assert(l < r); return this->rotate(l, l + uni::mod(-count, r - l), r); } // Find the min / max k in [l, r) that satisfies (this[k] + x) != x. // If no such k is found, return -1. template<bool LEFT = true> inline auto find(const size_type l, const size_type r, const value_type& val) noexcept(NO_EXCEPT) { return this->template find<LEFT>(l, r - 1, r); } // Find the min / max k in whole that satisfies (this[k] + x) != x. // If no such k is found, return -1. template<bool LEFT = true> inline auto find(const value_type& val) noexcept(NO_EXCEPT) { return this->find<LEFT>(0, this->size(), val); } struct point_reference : internal::point_reference<dynamic_sequence, size_type> { point_reference(dynamic_sequence *const super, const size_type pos) noexcept(NO_EXCEPT) : internal::point_reference<dynamic_sequence, size_type>(super, pos) {} operator value_type() noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } auto val() noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } inline auto& operator=(const value_type& val) noexcept(NO_EXCEPT) { this->_super->set(this->_pos, val); return *this; } inline auto& operator+=(const value_type& val) noexcept(NO_EXCEPT) { this->_super->add(this->_pos, val); return *this; } inline auto& operator*=(const operator_type& val) noexcept(NO_EXCEPT) { this->_super->apply(this->_pos, val); return *this; } }; struct range_reference : internal::range_reference<dynamic_sequence, size_type> { range_reference(dynamic_sequence *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<dynamic_sequence, size_type>(super, l, r) {} inline auto clone() noexcept(NO_EXCEPT) { return this->_super->clone(this->_begin, this->_end); } inline auto fold() noexcept(NO_EXCEPT) { return this->_super->fold(this->_begin, this->_end); } inline auto& operator=(const value_type& val) noexcept(NO_EXCEPT) { this->_super->fill(this->_begin, this->_end, val); return *this; } inline auto& operator*=(const operator_type& val) noexcept(NO_EXCEPT) { this->_super->apply(this->_begin, this->_end, val); return *this; } // Find the min / max k in [l, r) that satisfies (this[k] + x) != x. // If no such k is found, return -1. template<bool LEFT = true> inline auto find(const value_type& val) noexcept(NO_EXCEPT) { return this->_super->template find<LEFT>(this->_begin, this->_end, val); } }; inline auto operator[](const size_type pos) noexcept(NO_EXCEPT) { return point_reference(this, pos); } inline auto operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return range_reference(this, l, r); } struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, dynamic_sequence, iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() noexcept(NO_EXCEPT) { return iterator(this, this->size()); } inline auto rbegin() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } inline auto traverse() const noexcept(NO_EXCEPT) { return typename sequence_core::traverser(this->_root); } using dumper::dump_rich; using dumper::_debug; debugger::debug_t dump_rich(const std::string prefix = " ") { return "\n" + this->dump_rich(this->_root, prefix); } debugger::debug_t _debug() { return "[ " + this->_debug(this->_root) + " ]"; } }; } // namespace uni #line 2 "data_structure/dynamic_set.hpp" #line 12 "data_structure/dynamic_set.hpp" #line 15 "data_structure/dynamic_set.hpp" #line 22 "data_structure/dynamic_set.hpp" #line 25 "data_structure/dynamic_set.hpp" #line 27 "data_structure/dynamic_set.hpp" #line 31 "data_structure/dynamic_set.hpp" #line 33 "data_structure/dynamic_set.hpp" #line 35 "data_structure/dynamic_set.hpp" #line 38 "data_structure/dynamic_set.hpp" #line 40 "data_structure/dynamic_set.hpp" namespace uni { namespace internal { namespace dynamic_tree_impl { template<class ActionOrValue, class Context> requires (!Context::LEAF_ONLY) struct set_core : internal::basic_core<ActionOrValue, set_core<ActionOrValue, Context>, Context> { private: using base = internal::basic_core<ActionOrValue, set_core, Context>; public: using base::base; using data_type = base::data_type; using operand = base::operand; using node_handler = typename base::node_handler; using node_type = typename base::node_type; using node_pointer = typename base::node_pointer; using size_type = typename base::size_type; inline void pull(const node_pointer tree) const noexcept(NO_EXCEPT) { tree->data.acc = tree->left->data.acc + tree->length * tree->data.val + tree->right->data.acc; } inline constexpr void push(const node_pointer) const noexcept(NO_EXCEPT) { /* do nothing */ } template<std::random_access_iterator I, std::sized_sentinel_for<I> S> node_pointer build(I first, S last) { std::vector<i64> val; val.assign(first, last); std::ranges::sort(val); return this->base::build(ALL(val)); } void insert(node_pointer& tree, const operand& val, const size_type count = 1) noexcept(NO_EXCEPT) { if(count == 0) return; if(count < 0) return this->erase(tree, val, -count); node_pointer t0, t1; this->split(tree, { val }, t0, t1); this->merge(tree, t0, this->create(val, count), t1); } void insert_unique(node_pointer& tree, const operand& val, const size_type count = 1) noexcept(NO_EXCEPT) { if(count == 0) return; if(count < 0) return this->erase(tree, val, -count); node_pointer t0, t1; bool exist = false; this->template split<false, true>(tree, { val }, t0, t1, &exist); if(exist) this->merge(tree, t0, t1); else this->merge(tree, t0, this->create(val, count), t1); } void erase(node_pointer& tree, const operand& val, const size_type count = 1) noexcept(NO_EXCEPT) { if(count == 0) return; if(count < 0) return this->insert(tree, val, -count); node_pointer t0, t1, t2; this->split(tree, { val }, t0, t1); this->split(t1, count, t1, t2); this->dispose(t1); this->merge(tree, t0, t2); } void erase_limit(node_pointer& tree, const operand& val, size_type count = 1) noexcept(NO_EXCEPT) { if(count == 0) return; if(count < 0) return this->insert(tree, val, -count); node_pointer t0, t1, t2, t3; this->split(tree, { val }, t0, t1); this->template split<true>(t1, { val }, t1, t3); if(count >= t1->size) count = t1->size; this->split(t1, count, t1, t2); this->dispose(t1); this->merge(t2, t0, t2); this->merge(tree, t2, t3); } auto fold(node_pointer tree, const size_type l, const size_type r) noexcept(NO_EXCEPT) { assert(0 <= l && l <= r && r <= tree->size); return this->base::fold(tree, l, r); } void erase(node_pointer& tree, const size_type l, const size_type r) noexcept(NO_EXCEPT) { assert(0 <= l && l <= r && r <= tree->size); this->base::erase(tree, l, r); } auto pop(node_pointer& tree, const size_type pos, const size_type count = 1) noexcept(NO_EXCEPT) { assert(0 <= pos && 0 <= count && pos + count <= tree->size); return this->base::pop(tree, pos, count); } auto get(node_pointer tree, const size_type pos) noexcept(NO_EXCEPT) { assert(0 <= pos && pos < tree->size); return this->base::get(tree, pos); } template<bool STRICT = false> auto find(node_pointer& tree, const operand& val) noexcept(NO_EXCEPT) { node_pointer t0, t1; this->template split<STRICT>(tree, { val }, t0, t1); const auto res = t0->size; this->merge(tree, t0, t1); return res; } auto equal_range(node_pointer& tree, const operand& val) noexcept(NO_EXCEPT) { node_pointer t0, t1, t2; this->template split<true>(tree, { val }, t1, t2); this->split(t1, { val }, t0, t1); const auto lower = t0->size; this->merge(t1, t0, t1); const auto upper = t1->size; this->merge(tree, t1, t2); return std::make_pair(std::move(lower), std::move(upper)); } }; } // namespace dynamic_tree_impl } // namespace internal template<class Value, class Context = treap_context<>> struct dynamic_set : dynamic_set<actions::make_full_t<Value>, Context> { using dynamic_set<actions::make_full_t<Value>, Context>::dynamic_set; }; template<actions::internal::full_action ActionOrValue, class Context> requires internal::available_with<internal::dynamic_tree_impl::set_core, ActionOrValue, Context> struct dynamic_set<ActionOrValue, Context> : private internal::dumpable_tree< dynamic_set<ActionOrValue, Context>, internal::dynamic_tree_impl::set_core<ActionOrValue, Context>, Context::LEAF_ONLY > { public: using action = ActionOrValue; using operand = typename action::operand; using value_type = operand; using set_core = internal::dynamic_tree_impl::set_core<ActionOrValue, Context>; using node_handler = typename set_core::node_handler; using allocator_type = typename set_core::allocator_type; using node_type = typename set_core::node_type; using node_pointer = typename set_core::node_pointer; using size_type = typename set_core::size_type; private: using dumper = internal::dumpable_tree<dynamic_set, set_core, Context::LEAF_ONLY>; friend dumper; set_core _impl; node_pointer _root = node_handler::nil; size_type _offset = 0; public: ~dynamic_set() { this->_impl.dispose(this->_root); } dynamic_set(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator) {}; template<std::input_iterator I, std::sized_sentinel_for<I> S> dynamic_set(I first, S last, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator) { this->assign(first, last); } explicit dynamic_set(const size_type size, const value_type& val, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _impl(allocator) { this->assign(size, val); } explicit dynamic_set(const size_type size, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_set(size, value_type{}, allocator) {} template<std::ranges::input_range R> explicit dynamic_set(R&& range, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_set(ALL(range), allocator) {} template<std::convertible_to<value_type> T> dynamic_set(const std::initializer_list<T>& values, const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : dynamic_set(values, allocator) {} inline node_pointer& root() noexcept(NO_EXCEPT) { return this->_root; } inline const node_pointer& root() const noexcept(NO_EXCEPT) { return this->_root; } size_type size() const noexcept(NO_EXCEPT) { return this->_root->size; } bool empty() const noexcept(NO_EXCEPT) { return this->size() == 0; } template<internal::resizable_range Container> inline auto to() noexcept(NO_EXCEPT) { Container res; res.resize(this->size()); auto itr = std::ranges::begin(res); this->_impl.enumerate(this->_root, itr); return res; } inline void clear() noexcept(NO_EXCEPT) { this->_impl.dispose(this->_root); this->_root = node_handler::nil; } template<bool UNIQUE = false, std::input_iterator I, std::sized_sentinel_for<I> S> inline auto& assign(I first, S last) noexcept(NO_EXCEPT) { this->clear(); this->insert<UNIQUE>(first, last); return *this; } template<bool UNIQUE = false> inline auto& assign(const size_type size, const value_type& val = value_type{}) noexcept(NO_EXCEPT) { this->clear(); this->insert<UNIQUE>(val, size); return *this; } template<bool UNIQUE = false, std::ranges::input_range R> inline auto& assign(R&& range) noexcept(NO_EXCEPT) { return this->assign<UNIQUE>(ALL(range)); } template<bool UNIQUE = false, std::convertible_to<value_type> T> inline auto& assign(const std::initializer_list<T>& values) noexcept(NO_EXCEPT) { return this->assign<UNIQUE>(values); } template<bool UNIQUE = false> inline auto& insert(const operand& val, const size_type count = 1) noexcept(NO_EXCEPT) { if constexpr(UNIQUE) this->_impl.insert_unique(this->_root, val, count); else this->_impl.insert(this->_root, val, count); return *this; } template<bool UNIQUE = false, std::input_iterator I, std::sized_sentinel_for<I> S> inline auto& insert(I first, S last) noexcept(NO_EXCEPT) { for(; first != last; ++first) this->template insert<UNIQUE>(*first); return *this; } template<bool UNIQUE = false, std::ranges::input_range R> inline auto& insert(R&& range) noexcept(NO_EXCEPT) { return this->template insert<UNIQUE>(ALL(range)); } inline auto& fill(const value_type& val) noexcept(NO_EXCEPT) { const size_type size = this->size(); this->clear(); this->insert(val, size); return *this; } template<bool LIMIT = true> inline auto& erase(const value_type& val, const size_type count = 1) noexcept(NO_EXCEPT) { if constexpr(LIMIT) this->_impl.erase_limit(this->_root, val, count); else this->_impl.erase(this->_root, val, count); return *this; } inline auto& erase(const size_type l, const size_type r) noexcept(NO_EXCEPT) { this->_impl.erase(this->_root, l, r); return *this; } inline value_type pop(const size_type pos, const size_type count = 1) noexcept(NO_EXCEPT) { return this->_impl.pop(this->_root, pos, count); } inline value_type pop_min(const size_type count = 1) noexcept(NO_EXCEPT) { return this->pop(0, count); } inline value_type pop_max(const size_type count = 1) noexcept(NO_EXCEPT) { return this->pop(this->size() - count, count); } inline operand fold(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return this->_impl.fold(this->_root, l, r); } inline value_type get(const size_type k) noexcept(NO_EXCEPT) { return this->_impl.get(this->_root, k); } inline operand median(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return this->get((r - l) >> 1); } inline value_type min() noexcept(NO_EXCEPT) { return this->get(0); } inline value_type median() noexcept(NO_EXCEPT) { return this->get(this->size() >> 1); } inline value_type max() noexcept(NO_EXCEPT) { return this->get(this->size() - 1); } inline auto fold() noexcept(NO_EXCEPT) { return this->_root->data.acc; } inline value_type operator[](const size_type k) noexcept(NO_EXCEPT) { return this->get(k); } inline value_type operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return this->fold(l, r); } struct iterator; inline auto lower_bound(const value_type& val) noexcept(NO_EXCEPT) { return iterator{ this, this->_impl.template find<false>(this->_root, val) }; } inline auto upper_bound(const value_type& val) noexcept(NO_EXCEPT) { return iterator{ this, this->_impl.template find<true>(this->_root, val) }; } inline auto equal_range(const value_type& val) noexcept(NO_EXCEPT) { const auto [ lower, upper ] = this->_impl.equal_range(this->_root, val); return std::make_pair(iterator{ this, lower }, iterator{ this, upper }); } inline size_type count(const value_type& val) noexcept(NO_EXCEPT) { const auto [ lower, upper ] = this->_impl.equal_range(this->_root, val); return upper - lower; } inline bool contains(const value_type& val) noexcept(NO_EXCEPT) { return this->count(val) == 1; } inline auto& erase(const iterator& itr) noexcept(NO_EXCEPT) { return this->erase(itr.pos(), itr.pos() + 1); } inline auto& erase(const iterator& l, const iterator& r) noexcept(NO_EXCEPT) { return this->erase(l.pos(), r.pos()); } protected: using iterator_interface = internal::container_iterator_interface<value_type,dynamic_set,iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() noexcept(NO_EXCEPT) { return iterator{ this, 0 }; } inline auto end() noexcept(NO_EXCEPT) { return iterator{ this, this->size() }; } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } using dumper::dump_rich; using dumper::_debug; debugger::debug_t dump_rich(const std::string prefix = " ") { return "\n" + this->dump_rich(this->_root, prefix); } debugger::debug_t _debug() { return "[ " + this->_debug(this->_root) + " ]"; } }; } // namespace uni #line 2 "data_structure/fenwick_tree.hpp" #line 12 "data_structure/fenwick_tree.hpp" #line 21 "data_structure/fenwick_tree.hpp" #line 24 "data_structure/fenwick_tree.hpp" #line 27 "data_structure/fenwick_tree.hpp" namespace uni { namespace internal { namespace fenwick_tree_impl { // Thanks to: atcoder::fenwick_tree template<algebraic::internal::monoid Operand> struct core { using operand = Operand; using size_type = internal::size_t; private: size_type _n = 0, _bit_ceil = 0; std::vector<operand> _data; inline void _init() noexcept(NO_EXCEPT) { FOR(i, 1, this->_n) { size_type j = i + (i & -i); if(j <= this->_n) this->_data[j-1] = this->_data[j-1] + this->_data[i-1]; } } public: core() noexcept(NO_EXCEPT) {} explicit core(const size_type n) noexcept(NO_EXCEPT) : _n(n), _bit_ceil(std::bit_ceil<std::make_unsigned_t<size_type>>(n)), _data(n, operand{}) {} inline size_type size() const noexcept(NO_EXCEPT) { return this->_n; } template<std::input_iterator I, std::sentinel_for<I> S> inline void assign(I first, S last) noexcept(NO_EXCEPT) { if constexpr(std::sized_sentinel_for<S, I>) { assert(std::ranges::distance(first, last) == this->size()); } for(size_type i = 0; first < last; ++i, ++first) this->_data[i] = *first; this->_init(); } inline void add(size_type p, const operand& x) noexcept(NO_EXCEPT) { for(p++; p<=this->_n; p += p & -p) this->_data[p-1] = this->_data[p-1] + x; } inline void set(const size_type p, const operand& x) noexcept(NO_EXCEPT) { assert(this->get(p) == this->fold(p, p+1)); this->add(p, x + -this->get(p)); } inline operand fold(size_type r) const noexcept(NO_EXCEPT) { operand s = operand{}; for(; r>0; r -= r & -r) s = s + this->_data[r-1]; return s; } inline operand fold(size_type l, size_type r) const noexcept(NO_EXCEPT) { operand s = operand{}; for(; l < r; r -= r & -r) s = s + this->_data[r-1]; for(; r < l; l -= l & -l) s = s + -this->_data[l-1]; return s; } inline operand get(size_type p) const noexcept(NO_EXCEPT) { return this->fold(p, p+1); } template<class F> inline size_type max_right(size_type l, F&& f) const noexcept(NO_EXCEPT) requires algebraic::internal::invertible<operand> { assert(0 <= l && l <= this->_n); assert(f(operand{})); if(l == this->_n) return this->_n; operand inv = -this->fold(l); size_type p = 0, q = this->_bit_ceil; for(size_type k=q; k>0; k >>= 1) { if(p+k <= this->_n and f(this->_data[p+k-1] + inv)) { inv = inv + this->_data[(p+=k)-1]; } } return p; } template<class F> inline size_type min_left(size_type r, F&& f) const noexcept(NO_EXCEPT) requires algebraic::internal::invertible<operand> { assert(0 <= r && r <= this->_n); assert(f(operand{})); if(r == 0) return 0; operand acc = this->fold(r); size_type p = 0, q = std::bit_ceil<std::make_unsigned_t<size_type>>(r); for(size_type k=q; k>0; k >>= 1) { if(p+k < r and !f(acc + -this->_data[p+k-1])) { acc = acc + -this->_data[(p+=k)-1]; } } if(p == 0 and f(acc)) return 0; return p + 1; } }; } // namespace fenwick_tree_impl } // namespace internal template<class Value> struct fenwick_tree : internal::unconstructible {}; template<algebraic::internal::monoid Monoid> struct fenwick_tree<Monoid> : internal::fenwick_tree_impl::core<Monoid> { static_assert(algebraic::internal::commutative<Monoid>); private: using core = typename internal::fenwick_tree_impl::core<Monoid>; core _impl; public: using value_type = typename core::operand; using size_type = typename core::size_type; protected: inline size_type _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->_impl.size() + p : p; } public: fenwick_tree() noexcept(NO_EXCEPT) : _impl() {} explicit fenwick_tree(const size_type n) noexcept(NO_EXCEPT) : _impl(n) {} explicit fenwick_tree(const size_type n, const value_type& v) noexcept(NO_EXCEPT) : _impl(n) { this->_impl.fill(v); } template<std::convertible_to<value_type> T> fenwick_tree(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) : fenwick_tree(ALL(init_list)) {} template<std::input_iterator I, std::sized_sentinel_for<I> S> explicit fenwick_tree(I first, S last) noexcept(NO_EXCEPT) : fenwick_tree(static_cast<size_type>(std::ranges::distance(first, last))) { this->assign(first, last); } template<std::ranges::input_range R> explicit fenwick_tree(R&& range) noexcept(NO_EXCEPT) : fenwick_tree(ALL(range)) {} template<std::convertible_to<value_type> T> inline auto& assign(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT){ return this->assign(ALL(init_list)); } template<std::input_iterator I, std::sentinel_for<I> S> inline auto& assign(I first, S last) noexcept(NO_EXCEPT) { this->_impl.assign(first, last); return *this; } template<std::ranges::input_range R> inline auto& assign(R&& range) noexcept(NO_EXCEPT) { return this->assign(ALL(range)); } inline auto& fill(const value_type& v = value_type()) noexcept(NO_EXCEPT) { std::fill(this->data(), this->data() + this->_impl.size(), v); this->_init(); return *this; } inline auto size() const noexcept(NO_EXCEPT) { return this->_impl.size(); } inline bool empty() const noexcept(NO_EXCEPT) { return this->_impl.size() == 0; } struct point_reference : internal::point_reference<fenwick_tree> { point_reference(fenwick_tree *const super, const size_type p) noexcept(NO_EXCEPT) : internal::point_reference<fenwick_tree>(super, super->_positivize_index(p)) { assert(0 <= this->_pos && this->_pos < this->_super->size()); } operator value_type() const noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } auto val() const noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } inline auto& operator=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->set(this->_pos, v); return *this; } inline auto& operator+=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->add(this->_pos, v); return *this; } }; struct range_reference : internal::range_reference<fenwick_tree> { range_reference(fenwick_tree *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<fenwick_tree>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->size()); } inline auto fold() noexcept(NO_EXCEPT) { if(this->_begin == 0 and this->_end == this->_super->size()) return this->_super->fold(); if(this->_begin == 0) return this->_super->fold(this->_end); return this->_super->fold(this->_begin, this->_end); } }; inline auto& add(const size_type p, const value_type& x) noexcept(NO_EXCEPT) { assert(0 <= p && p < this->_impl.size()); this->_impl.add(p, x); return *this; } inline auto& set(const size_type p, const value_type& x) noexcept(NO_EXCEPT) requires algebraic::internal::invertible<value_type> { assert(0 <= p && p < this->_impl.size()); this->_impl.set(p, x); return *this; } inline value_type get(const size_type p) const noexcept(NO_EXCEPT) requires algebraic::internal::invertible<value_type> { assert(0 <= p && p < this->_impl.size()); return this->_impl.get(p); } inline auto operator[](const size_type p) noexcept(NO_EXCEPT) { return point_reference(this, p); } inline const auto operator()(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto fold(const size_type l, const size_type r) const noexcept(NO_EXCEPT) requires algebraic::internal::invertible<value_type> { assert(0 <= l && l <= r && r <= this->_impl.size()); return this->_impl.fold(l, r); } inline auto fold(const size_type r) const noexcept(NO_EXCEPT) { assert(0 <= r && r <= this->_impl.size()); return this->_impl.fold(r); } inline auto fold() const noexcept(NO_EXCEPT) { return this->_impl.fold(this->_impl.size()); } struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, const fenwick_tree, iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, this->_impl.size()); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } }; template<actions::internal::operatable_action Action> struct fenwick_tree<Action> : fenwick_tree<typename Action::operand> { using fenwick_tree<typename Action::operand>::fenwick_tree; }; } // namespace uni #line 2 "data_structure/foldable_deque.hpp" #line 6 "data_structure/foldable_deque.hpp" #line 9 "data_structure/foldable_deque.hpp" #line 12 "data_structure/foldable_deque.hpp" #line 14 "data_structure/foldable_deque.hpp" #line 2 "data_structure/foldable_stack.hpp" #line 6 "data_structure/foldable_stack.hpp" #line 10 "data_structure/foldable_stack.hpp" #line 14 "data_structure/foldable_stack.hpp" #line 17 "data_structure/foldable_stack.hpp" #line 19 "data_structure/foldable_stack.hpp" namespace uni { template<class, template<class...> class = stack> struct foldable_stack : internal::unconstructible {}; template<algebraic::internal::monoid Monoid, template<class...> class Stack> struct foldable_stack<Monoid, Stack> { using fold_type = Monoid; using value_type = Monoid::value_type; using size_type = Stack<Monoid>::size_type; Stack<value_type> _val; Stack<fold_type> _acc; inline bool empty() const noexcept(NO_EXCEPT) { return this->_val.empty(); } inline auto size() const noexcept(NO_EXCEPT) { return this->_val.size(); } inline decltype(auto) top() const noexcept(NO_EXCEPT) { assert(!this->empty()); return this->_val.top(); } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline decltype(auto) top_or(T&& val) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(val)); else return this->top(); } inline auto fold() const noexcept(NO_EXCEPT) { if(this->empty()) return fold_type(); return this->_acc.top(); } template<std::convertible_to<fold_type> T = value_type> auto& push(T&& x) noexcept(NO_EXCEPT) { const auto acc = this->fold(); this->_val.push(x); this->_acc.push(acc + std::forward<T>(x)); return *this; } template<class... Args> decltype(auto) emplace(Args&&... args) noexcept(NO_EXCEPT) { const auto acc = this->fold(); decltype(auto) res = this->_val.emplace(std::forward<Args>(args)...); this->_acc.push(acc + res); return res; } inline auto& pop() noexcept(NO_EXCEPT) { this->_val.pop(), this->_acc.pop(); return *this; } }; template<actions::internal::operatable_action Action, template<class...> class Stack> struct foldable_stack<Action, Stack> : foldable_stack<typename Action::operand> { using foldable_stack<typename Action::operand>::foldable_stack; }; } // namespace uni #line 16 "data_structure/foldable_deque.hpp" namespace uni { namespace internal { template<algebraic::internal::monoid Monoid, template<class...> class Stack> using foldable_deque_base = deque_by_stack<foldable_stack<algebraic::make_opposite_t<Monoid>, Stack>, foldable_stack<Monoid, Stack>>; } // namespace internal template<class, template<class...> class = stack> struct foldable_deque : internal::unconstructible {}; template<algebraic::internal::monoid Monoid, template<class...> class Stack> struct foldable_deque<Monoid, Stack> : internal::foldable_deque_base<Monoid, Stack> { using internal::foldable_deque_base<Monoid, Stack>::foldable_deque_base; inline auto fold() const noexcept(NO_EXCEPT) { return Monoid(this->_front.fold()) + this->_back.fold(); } }; template<actions::internal::operatable_action Action, template<class...> class Stack> struct foldable_deque<Action, Stack> : foldable_deque<typename Action::operand> { using foldable_deque<typename Action::operand>::foldable_deque; }; } // namespace uni #line 2 "data_structure/foldable_queue.hpp" #line 6 "data_structure/foldable_queue.hpp" #line 9 "data_structure/foldable_queue.hpp" #line 12 "data_structure/foldable_queue.hpp" #line 14 "data_structure/foldable_queue.hpp" #line 16 "data_structure/foldable_queue.hpp" namespace uni { namespace internal { template<algebraic::internal::monoid Monoid, template<class...> class Stack> using foldable_queue_base = queue_by_stack<foldable_stack<Monoid, Stack>, foldable_stack<algebraic::make_opposite_t<Monoid>, Stack>>; } // namespace internal template<class, template<class...> class = stack> struct foldable_queue : internal::unconstructible {}; template<algebraic::internal::monoid Monoid, template<class...> class Stack> struct foldable_queue<Monoid, Stack> : internal::foldable_queue_base<Monoid, Stack> { using internal::foldable_queue_base<Monoid, Stack>::foldable_queue_base; inline auto fold() const noexcept(NO_EXCEPT) { return Monoid(this->_out.fold()) + this->_in.fold(); } }; template<actions::internal::operatable_action Action, template<class...> class Stack> struct foldable_queue<Action, Stack> : foldable_queue<typename Action::operand> { using foldable_queue<typename Action::operand>::foldable_queue; }; } // namespace uni #line 2 "data_structure/kth_element.hpp" #line 11 "data_structure/kth_element.hpp" #line 15 "data_structure/kth_element.hpp" namespace uni { // Thanks to: https://qiita.com/drken/items/1b7e6e459c24a83bb7fd template< class T, std::ranges::output_range<T> Container = std::vector<T>, std::strict_weak_order<T, T> Comparer = std::less<T>, std::strict_weak_order<T, T> RevComparer = std::greater<T>, std::integral Size = internal::size_t > struct kth_element { using value_type = T; using size_type = Size; protected: size_type _k; std::priority_queue<T, Container, Comparer> _small; std::priority_queue<T, Container, RevComparer> _large; public: kth_element(const size_type k = 0) noexcept(NO_EXCEPT) : _k(k + 1) { assert(k >= 0); } inline bool has() const noexcept(NO_EXCEPT) { return std::ssize(this->_small) == this->_k; } inline value_type value() const noexcept(NO_EXCEPT) { return this->_small.top(); } inline std::optional<value_type> get() const noexcept(NO_EXCEPT) { if(this->has()) return this->value(); return {}; } template<std::convertible_to<T> U = T> inline auto value_or(U&& v) const noexcept(NO_EXCEPT) { return this->get().value_or(std::forward<U>(v)); } inline void push(const value_type& v) noexcept(NO_EXCEPT) { if(std::ssize(this->_small) < this->_k) { this->_small.push(v); return; } const auto kth = this->_small.top(); if(Comparer{}(v, kth)) { this->_small.pop(); this->_small.push(v); this->_large.push(kth); } else { this->_large.push(v); } } inline void pop() noexcept(NO_EXCEPT) { assert(this->has()); this->_small.pop(); if(this->_large.empty()) return; const auto v = this->_large.top(); this->_large.pop(); this->_small.push(v); } }; } // namespace uni #line 2 "data_structure/lazy_segment_tree.hpp" #line 12 "data_structure/lazy_segment_tree.hpp" #line 15 "data_structure/lazy_segment_tree.hpp" #line 21 "data_structure/lazy_segment_tree.hpp" #line 24 "data_structure/lazy_segment_tree.hpp" #line 26 "data_structure/lazy_segment_tree.hpp" #line 29 "data_structure/lazy_segment_tree.hpp" namespace uni { namespace internal { namespace lazy_segment_tree_impl { // Thanks to: atcoder::lazy_segtree template<actions::internal::full_action Action> requires algebraic::internal::monoid<typename Action::operand> && algebraic::internal::monoid<typename Action::operation> struct core { using size_type = internal::size_t; using action = Action; using operand = typename Action::operand; using operation = typename Action::operation; private: size_type _n = 0, _size = 0, _depth = 0; std::valarray<size_type> _lengths; std::valarray<operand> _values; std::valarray<operation> _lazy; inline void _pull(const size_type p) noexcept(NO_EXCEPT) { this->_values[p] = this->_values[p << 1] + this->_values[p << 1 | 1]; } inline void _all_apply(const size_type p, const operation& f) noexcept(NO_EXCEPT) { this->_values[p] = action::mapping(action::power(f, this->_lengths[p]), this->_values[p]); if(p < this->_size) this->_lazy[p] = f + this->_lazy[p]; } inline void _push(const size_type p) noexcept(NO_EXCEPT) { this->_all_apply(p << 1, this->_lazy[p]); this->_all_apply(p << 1 | 1, this->_lazy[p]); this->_lazy[p] = operation{}; } inline void _init() noexcept(NO_EXCEPT) { REPD(p, 1, this->_size) { this->_lengths[p] = this->_lengths[p << 1] + this->_lengths[p << 1 | 1]; this->_pull(p); } } public: core() noexcept = default; explicit core(const size_type n) noexcept(NO_EXCEPT) : _n(n), _size(std::bit_ceil(uni::to_unsigned(n))), _depth(std::countr_zero(uni::to_unsigned(this->_size))), _lengths(this->_size << 1), _values(this->_size << 1), _lazy(this->_size) {} inline size_type size() const noexcept(NO_EXCEPT) { return this->_n; } inline size_type allocated() const noexcept(NO_EXCEPT) { return this->_values.size(); } inline size_type depth() const noexcept(NO_EXCEPT) { return this->_depth; } inline operand fold_all() const noexcept(NO_EXCEPT) { return this->_values[1]; } inline void fill( const operand& v = operand()) noexcept(NO_EXCEPT) { REP(p, 0, this->_n) { this->_lengths[this->_size + p] = 1, this->_values[this->_size + p] = v; } this->_init(); } template<std::input_iterator I, std::sentinel_for<I> S> inline void assign(I first, S last) noexcept(NO_EXCEPT) { if constexpr(std::sized_sentinel_for<operand, I>) { assert(std::ranges::distance(first, last) == this->_n); } size_type p = 0; for(auto itr=first; itr!=last; ++itr, ++p) { this->_lengths[this->_size + p] = 1, this->_values[this->_size + p] = static_cast<operand>(*itr); } this->_init(); } inline void set(size_type p, const operand& x) noexcept(NO_EXCEPT) { p += this->_size; FORD(i, 1, this->_depth) this->_push(p >> i); this->_values[p] = x; FOR(i, 1, this->_depth) this->_pull(p >> i); } inline void add(size_type p, const operand& x) noexcept(NO_EXCEPT) { p += this->_size; FORD(i, 1, this->_depth) this->_push(p >> i); this->_values[p] = this->_values[p] + x; FOR(i, 1, this->_depth) this->_pull(p >> i); } inline operand get(size_type p) noexcept(NO_EXCEPT) { p += this->_size; FORD(i, 1, this->_depth) this->_push(p >> i); return this->_values[p]; } inline operand fold(size_type l, size_type r) noexcept(NO_EXCEPT) { if(l == r) return {}; l += this->_size; r += this->_size; FORD(i, 1, this->_depth) { if(((l >> i) << i) != l) this->_push(l >> i); if(((r >> i) << i) != r) this->_push((r - 1) >> i); } operand sml = operand{}, smr = operand{}; while(l < r) { if(l & 1) sml = sml + this->_values[l++]; if(r & 1) smr = this->_values[--r] + smr; l >>= 1; r >>= 1; } return sml + smr; } inline void apply(size_type p, const operation& f) noexcept(NO_EXCEPT) { p += this->_size; FORD(i, 1, this->_depth) this->_push(p >> i); this->_values[p] = action::mapping(action::power(f, this->_lengths[p]), this->_values[p]); FOR(i, 1, this->_depth) this->_pull(p >> i); } inline void apply(size_type l, size_type r, const operation& f) noexcept(NO_EXCEPT) { if(l == r) return; l += this->_size; r += this->_size; FORD(i, 1, this->_depth) { if(((l >> i) << i) != l) this->_push(l >> i); if(((r >> i) << i) != r) this->_push((r - 1) >> i); } { size_type l2 = l, r2 = r; while(l < r) { if(l & 1) this->_all_apply(l++, f); if(r & 1) this->_all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; } FOR(i, 1, this->_depth) { if(((l >> i) << i) != l) this->_pull(l >> i); if(((r >> i) << i) != r) this->_pull((r - 1) >> i); } } template<class F> inline size_type max_right(size_type l, F&& f) noexcept(NO_EXCEPT) { assert(0 <= l && l <= _n); assert(f(operand{})); if(l == _n) return _n; l += this->_size; FORD(i, 1, this->_depth) this->_push(l >> i); operand sm; do { while(l % 2 == 0) l >>= 1; if(!f(sm + this->_values[l])) { while(l < this->_size) { this->_push(l); l = (2 * l); if(f(sm + this->_values[l])) { sm = sm + this->_values[l]; l++; } } return l - this->_size; } sm = sm + this->_values[l]; l++; } while((l & -l) != l); return _n; } template<class F> inline size_type min_left(size_type r, F&& f) noexcept(NO_EXCEPT) { assert(0 <= r && r <= _n); assert(f(operand{})); if(r == 0) return 0; r += this->_size; FORD(i, 1, this->_depth) this->_push((r - 1) >> i); operand sm; do { r--; while(r > 1 && (r % 2)) r >>= 1; if(!f(this->_values[r] + sm)) { while(r < this->_size) { this->_push(r); r = (2 * r + 1); if(f(this->_values[r] + sm)) { sm = this->_values[r] + sm; r--; } } return r + 1 - this->_size; } sm = this->_values[r] + sm; } while((r & -r) != r); return 0; } }; } // namespace lazy_segment_tree_impl } // namespace internal template<class T> struct lazy_segment_tree : lazy_segment_tree<actions::make_full_t<T>> { using lazy_segment_tree<actions::make_full_t<T>>::lazy_segment_tree; }; template<actions::internal::full_action Action> requires internal::available<internal::lazy_segment_tree_impl::core<Action>> struct lazy_segment_tree<Action> { using action = Action; using operand = Action::operand; using operation = Action::operation; private: using core = internal::lazy_segment_tree_impl::core<action>; core _impl; public: using value_type = operand; using action_type = operation::value_type; using size_type = core::size_type; inline auto size() const noexcept(NO_EXCEPT) { return this->_impl.size(); } inline auto allocated() const noexcept(NO_EXCEPT) { return this->_impl.allocated(); } inline auto depth() const noexcept(NO_EXCEPT) { return this->_impl.depth(); } protected: inline size_type _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->_impl.size() + p : p; } public: lazy_segment_tree() noexcept(NO_EXCEPT) : _impl() {} explicit lazy_segment_tree(const size_type n, const value_type& v = value_type()) noexcept(NO_EXCEPT) : _impl(n) { this->_impl.fill(v); } template<std::convertible_to<value_type> T> lazy_segment_tree(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) : lazy_segment_tree(ALL(init_list)) {} template<std::input_iterator I, std::sized_sentinel_for<I> S> lazy_segment_tree(I first, S last) noexcept(NO_EXCEPT) : _impl(static_cast<size_type>(std::ranges::distance(first, last))) { this->assign(first, last); } template<std::ranges::input_range R> explicit lazy_segment_tree(R&& range) noexcept(NO_EXCEPT) : lazy_segment_tree(ALL(range)) {} template<std::convertible_to<value_type> T> inline auto& assign(const std::initializer_list<T>& init_list) noexcept(NO_EXCEPT) { return this->assign(ALL(init_list)); } template<std::input_iterator I, std::sentinel_for<I> S> inline auto& assign(I first, S last) noexcept(NO_EXCEPT) { this->_impl.assign(first, last); return *this; } template<std::ranges::input_range R> inline auto& assign(R&& range) noexcept(NO_EXCEPT) { return this->assign(ALL(range)); } inline auto& fill( const value_type& v = value_type()) noexcept(NO_EXCEPT) { this->impl.fill(v); return *this; } bool empty() const noexcept(NO_EXCEPT) { return this->_impl.size() == 0; } struct point_reference : internal::point_reference<lazy_segment_tree> { point_reference(lazy_segment_tree *const super, const size_type p) noexcept(NO_EXCEPT) : internal::point_reference<lazy_segment_tree>(super, super->_positivize_index(p)) { assert(0 <= this->_pos && this->_pos < this->_super->size()); } operator value_type() noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } auto val() noexcept(NO_EXCEPT) { return this->_super->get(this->_pos); } inline auto& operator=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->set(this->_pos, v); return *this; } inline auto& operator+=(const value_type& v) noexcept(NO_EXCEPT) { this->_super->add(this->_pos, v); return *this; } inline auto& operator*=(const action_type& v) noexcept(NO_EXCEPT) { this->_super->apply(this->_pos, v); return *this; } }; struct range_reference : internal::range_reference<lazy_segment_tree> { range_reference(lazy_segment_tree *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<lazy_segment_tree>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->size()); } inline auto& operator*=(const action_type& v) noexcept(NO_EXCEPT) { this->_super->apply(this->_begin, this->_end, v); return *this; } inline auto fold() noexcept(NO_EXCEPT) { if(this->_begin == 0 && this->_end == this->_super->size()) return this->_super->fold(); return this->_super->fold(this->_begin, this->_end); } }; inline auto& set(size_type p, const value_type& v) noexcept(NO_EXCEPT) { p = this->_positivize_index(p), assert(0 <= p && p < this->_impl.size()); this->_impl.set(p, v); return *this; } inline auto& add(size_type p, const value_type& v) noexcept(NO_EXCEPT) { p = this->_positivize_index(p), assert(0 <= p && p < this->_impl.size()); this->_impl.add(p, v); return *this; } inline auto& apply(size_type l, size_type r, const action_type& v) noexcept(NO_EXCEPT) { l = this->_positivize_index(l), r = this->_positivize_index(r); assert(0 <= l && l <= r && r <= this->_impl.size()); this->_impl.apply(l, r, v); return *this; } inline auto& apply(const size_type p, const action_type& v) noexcept(NO_EXCEPT) { this->apply(p, p + 1, v); return *this; } inline auto& apply(const action_type& v) noexcept(NO_EXCEPT) { this->apply(0, this->_impl.size(), v); return *this; } inline auto get(size_type p) noexcept(NO_EXCEPT) { p = this->_positivize_index(p), assert(0 <= p && p < this->_impl.size()); return this->_impl.get(p); } inline auto operator[](const size_type p) noexcept(NO_EXCEPT) { return point_reference(this, p); } inline auto operator()(const size_type l, const size_type r) noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto fold(size_type l, size_type r) noexcept(NO_EXCEPT) { l = this->_positivize_index(l), r = this->_positivize_index(r); assert(0 <= l && l <= r && r <= this->_impl.size()); return this->_impl.fold(l, r); } inline auto fold() noexcept(NO_EXCEPT) { return this->_impl.fold_all(); } template<bool (*f)(value_type)> inline auto max_right(const size_type l) noexcept(NO_EXCEPT) { return this->max_right(l, [](operand x) { return f(x); }); } template<class F> inline auto max_right(const size_type l, F&& f) noexcept(NO_EXCEPT) { return this->_impl.max_right(l, std::forward<F>(f)); } template<bool (*f)(value_type)> inline auto min_left(const size_type r) noexcept(NO_EXCEPT) { return min_left(r, [](operand x) { return f(x); }); } template<class F> inline auto min_left(const size_type r, F&& f) noexcept(NO_EXCEPT) { return this->_impl.min_left(r, std::forward<F>(f)); } struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, lazy_segment_tree, iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() noexcept(NO_EXCEPT) { return iterator(this, this->_impl.size()); } inline auto rbegin() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } }; } // namespace uni #line 2 "data_structure/persistent_queue.hpp" #line 9 "data_structure/persistent_queue.hpp" #line 12 "data_structure/persistent_queue.hpp" #line 16 "data_structure/persistent_queue.hpp" namespace uni { // Thanks to: https://tk0-math.hatenablog.com/entry/2020/03/27/194150 template<class ValueType, u32 BUFFER_DEPTH = 20, class Allocator = std::allocator<ValueType>> struct persistent_queue { using value_type = ValueType; using size_type = internal::size_t; struct node_type; using node_handler = node_handlers::cloneable<Allocator>::template handler<node_type>; using node_pointer = typename node_handler::node_pointer; using allocator_type = typename node_handler::allocator_type; struct node_type { value_type value; node_pointer prev[BUFFER_DEPTH]; }; private: size_type _size = 0; node_pointer _head, _tail; [[no_unique_address]] node_handler _node_handler; public: explicit persistent_queue(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _node_handler(allocator) {} persistent_queue(const persistent_queue& source, const allocator_type& allocator) noexcept(NO_EXCEPT) : _size(source._size), _head(source._head), _tail(source._tail), _node_handler(allocator) {} persistent_queue(persistent_queue&& source, const allocator_type& allocator) noexcept(NO_EXCEPT) : _size(source._size), _head(source._head), _tail(source._tail), _node_handler(allocator) {} inline auto clone() const noexcept(NO_EXCEPT) { return *this; } inline bool empty() const noexcept(NO_EXCEPT) { return this->_size == 0; } inline size_type size() const noexcept(NO_EXCEPT) { return this->_size; } inline value_type front() const noexcept(NO_EXCEPT) { assert(!this->empty()); return this->_head->value; } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline value_type front_or(T&& v) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(v)); else return this->front(); } inline value_type back() const noexcept(NO_EXCEPT) { assert(!this->empty()); return this->_tail->value; } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline value_type back_or(T&& v) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(v)); else return this->back(); } inline auto& clear() noexcept(NO_EXCEPT) { this->_head.reset(), this->_tail.reset(); this->_size = 0; return *this; } template<std::convertible_to<value_type> T = value_type> auto& push(T&& x) noexcept(NO_EXCEPT) { node_pointer node = this->_node_handler.create(x); node->prev[0] = this->_tail; REP(i, 1, BUFFER_DEPTH) { node_pointer prev = node->prev[i - 1]; if(prev) node->prev[i] = prev->prev[i - 1]; else break; } if(!this->_head) this->_head = node; this->_tail = node; ++this->_size; return *this; } auto& pop() noexcept(NO_EXCEPT) { assert(!this->empty()); if(!this->_head || !this->_tail || this->_size == 1) { this->clear(); return *this; } auto index = to_unsigned(this->_size - 2); node_pointer node = this->_tail; while(index != 0) { const size_type msb = uni::highest_bit_pos(index); index -= 1 << msb; node = node->prev[msb]; } this->_head = node; --this->_size; return *this; } }; namespace pmr { template<class T, u32 BUFFER_DEPTH = 20> using persistent_queue = uni::persistent_queue<T, BUFFER_DEPTH, std::pmr::polymorphic_allocator<T>>; } // namesapce pmr } // namespace uni #line 2 "data_structure/persistent_stack.hpp" #line 7 "data_structure/persistent_stack.hpp" #line 10 "data_structure/persistent_stack.hpp" #line 13 "data_structure/persistent_stack.hpp" namespace uni { template<class ValueType, class Allocator = std::allocator<ValueType>> struct persistent_stack { using value_type = ValueType; using size_type = internal::size_t; struct node_type; using node_handler = node_handlers::cloneable<Allocator>::template handler<node_type>; using allocator_type = typename node_handler::allocator_type; using node_pointer = typename node_handler::node_pointer; struct node_type { value_type value; node_pointer next; node_type(node_pointer _next, value_type _value) noexcept(NO_EXCEPT) : value(_value), next(_next) {} template<class... Args> node_type(node_pointer _next, Args&&... args) noexcept(NO_EXCEPT) : value(std::forward<Args>(args)...), next(_next) {} }; private: size_type _size = 0; node_pointer _head; [[no_unique_address]] node_handler _node_handler; public: explicit persistent_stack(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _node_handler(allocator) {}; persistent_stack(const persistent_stack& source, const allocator_type& allocator) noexcept(NO_EXCEPT) : _size(source._size), _head(source._head), _node_handler(allocator) {}; persistent_stack(persistent_stack&& source, const allocator_type& allocator) noexcept(NO_EXCEPT) : _size(source._size), _head(source._head), _node_handler(allocator) {}; inline auto clone() const noexcept(NO_EXCEPT) { return *this; } inline bool empty() const noexcept(NO_EXCEPT) { return !this->_head; } inline size_type size() const noexcept(NO_EXCEPT) { return this->_size; } inline value_type top() const noexcept(NO_EXCEPT) { assert(!this->empty()); return this->_head->value; } template<std::convertible_to<value_type> T = value_type> requires std::is_move_constructible_v<T> inline value_type top_or(T&& v) const noexcept(NO_EXCEPT) { if(this->empty()) return static_cast<value_type>(std::forward<T>(v)); else return this->top(); } inline auto& clear() noexcept(NO_EXCEPT) { this->_head.reset(); this->_size = 0; return *this; } template<std::convertible_to<value_type> T = value_type> inline auto& push(T&& x) noexcept(NO_EXCEPT) { this->_head = this->_node_handler.create(this->_head, std::forward<T>(x)); ++this->_size; return *this; } template<class... Args> inline auto& emplace(Args&&... args) noexcept(NO_EXCEPT) { this->_head = this->_node_handler.create(this->_head, std::forward<Args>(args)...); ++this->_size; return this->_head->value; } inline auto& pop() noexcept(NO_EXCEPT) { assert(!this->empty()); this->_head = this->_head->next; --this->_size; return *this; } }; namespace pmr { template<class T> using persistent_stack = uni::persistent_stack<T, std::pmr::polymorphic_allocator<T>>; } // namesapce pmr } // namespace uni #line 2 "data_structure/red_black_tree.hpp" #line 13 "data_structure/red_black_tree.hpp" #line 17 "data_structure/red_black_tree.hpp" #line 23 "data_structure/red_black_tree.hpp" #line 25 "data_structure/red_black_tree.hpp" #line 27 "data_structure/red_black_tree.hpp" #line 29 "data_structure/red_black_tree.hpp" #line 32 "data_structure/red_black_tree.hpp" namespace uni { namespace internal { // Thanks to: http://blog.mitaki28.info/1447078746296/ template<class NodeHandler, class Derived, std::integral SizeType, class ValueType> struct red_black_tree_impl { using size_type = SizeType; using rank_type = int; using value_type = ValueType; enum class node_colors : std::int8_t { RED, BLACK }; struct node_type; using node_handler = typename NodeHandler::handler<node_type>; using allocator_type = typename node_handler::allocator_type; using node_pointer = typename node_handler::node_pointer; struct node_type { node_pointer left = node_handler::nil, right = node_handler::nil; node_colors color = node_colors::BLACK; size_type size = 0; rank_type rank = 0; inline constexpr bool is_leaf() const noexcept(NO_EXCEPT) { return this->left == node_handler::nil && this->right == node_handler::nil; } [[no_unique_address]] value_type data; node_type() noexcept = default; node_type(const value_type& _data, const size_type _size) noexcept(NO_EXCEPT) : size(_size), data(_data) {} node_type(const node_colors _color, const node_pointer& _left, const node_pointer& _right) noexcept(NO_EXCEPT) : left(_left), right(_right), color(_color) {} }; private: using derived = Derived; inline auto* _derived() noexcept(NO_EXCEPT) { return static_cast<derived*>(this); } inline const auto* _derived() const noexcept(NO_EXCEPT) { return static_cast<const derived*>(this); } [[no_unique_address]] node_handler _node_handler; public: void pull(const node_pointer& tree) const noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return; if(tree->is_leaf()) return; tree->size = tree->left->size + tree->right->size; tree->rank = tree->left->rank + (tree->left->color == node_colors::BLACK); this->_derived()->pull(tree); } void push(node_pointer& tree) noexcept(NO_EXCEPT) { if(tree == node_handler::nil) return; this->clone(tree); this->_derived()->push(tree); this->pull(tree); } inline void clone(node_pointer& tree) noexcept(NO_EXCEPT) { tree = this->_node_handler.clone(tree); } node_pointer create(const value_type& val, const size_type size) noexcept(NO_EXCEPT) { if(size == 0) return node_handler::nil; return this->_node_handler.create(val, size); } node_pointer create(const node_colors color, node_pointer left, node_pointer right) noexcept(NO_EXCEPT) { this->push(left); this->push(right); return this->_node_handler.create(color, std::move(left), std::move(right)); } void dispose(const node_pointer& tree) noexcept(NO_EXCEPT) { if(this->_node_handler.disposable(tree)) { this->dispose(tree->left); this->dispose(tree->right); this->_node_handler.dispose(tree); } } private: void _as_root(node_pointer& node) { this->clone(node); if(node->color == node_colors::RED) node->color = node_colors::BLACK; this->push(node); } void _merge(node_pointer& tree, node_pointer left, node_pointer right) noexcept(NO_EXCEPT) { if(left->rank < right->rank) { this->push(right); this->_merge(tree, left, right->left); if(right->color == node_colors::BLACK && tree->color == node_colors::RED && tree->left->color == node_colors::RED) { tree->color = node_colors::BLACK; if(right->right->color == node_colors::BLACK) { this->clone(right); right->color = node_colors::RED; right->left = tree->right; this->pull(right); this->clone(tree); tree->right = std::move(right); } else { this->clone(right->right); right->right->color = node_colors::BLACK; this->clone(right); right->left = tree; right->color = node_colors::RED; tree = std::move(right); } } else { this->clone(right); right->left = tree; tree = std::move(right); } } else if(left->rank > right->rank) { this->push(left); this->_merge(tree, left->right, right); if(left->color == node_colors::BLACK && tree->color == node_colors::RED && tree->right->color == node_colors::RED) { tree->color = node_colors::BLACK; if(left->left->color == node_colors::BLACK) { this->clone(left); left->color = node_colors::RED; left->right = tree->left; this->pull(left); this->clone(tree); tree->left = std::move(left); } else { this->clone(left->left); left->left->color = node_colors::BLACK; this->clone(left); left->right = tree; left->color = node_colors::RED; tree = std::move(left); } } else { this->clone(left); left->right = tree; tree = std::move(left); } } else { tree = this->create(node_colors::RED, left, right); } this->pull(tree); } void _split(node_pointer tree, const size_type pos, node_pointer& left, node_pointer& right) { if(tree == node_handler::nil) { left = right = node_handler::nil; return; } this->push(tree); if(tree->is_leaf()) { left = this->create(tree->data, pos); right = this->create(tree->data, tree->size - pos); return; } auto l = std::move(tree->left), r = std::move(tree->right); this->_node_handler.dispose(tree); if(pos < l->size) { this->_split(std::move(l), pos, left, right); this->_as_root(r); this->merge(right, right, std::move(r)); this->_as_root(left); return; } if(pos > l->size) { this->_split(std::move(r), pos - l->size, left, right); this->_as_root(l); this->merge(left, std::move(l), left); this->_as_root(right); return; } left = std::move(l), right = std::move(r); this->_as_root(left), this->_as_root(right); } public: explicit red_black_tree_impl(const allocator_type& allocator = allocator_type()) noexcept(NO_EXCEPT) : _node_handler(allocator) {} template<std::random_access_iterator I, std::sized_sentinel_for<I> S> requires std::constructible_from<value_type, std::iter_value_t<I>> node_pointer build(I first, S last) noexcept(NO_EXCEPT) { if(first == last) return node_handler::nil; if(std::ranges::next(first) == last) return this->create(value_type{ *first }, 1); const auto length = std::ranges::distance(first, last); const auto middle = std::ranges::next(first, std::bit_floor(to_unsigned(length - 1))); node_pointer tree; this->merge(tree, this->build(std::move(first), middle), this->build(middle, std::move(last))); return tree; } template<std::random_access_iterator I, std::sized_sentinel_for<I> S> requires std::constructible_from<value_type, typename std::iter_value_t<I>::first_type> && std::integral<typename std::iter_value_t<I>::second_type> node_pointer build(I first, S last) noexcept(NO_EXCEPT) { if(first == last) return node_handler::nil; if(std::ranges::next(first) == last) return this->create(value_type{ first->first }, first->second); const auto length = std::ranges::distance(first, last); const auto middle = std::ranges::next(first, std::bit_floor(to_unsigned(length - 1))); node_pointer tree; this->merge(tree, this->build(std::move(first), middle), this->build(middle, std::move(last))); return tree; } void split(const node_pointer& tree, const size_type pos, node_pointer& left, node_pointer& right) noexcept(NO_EXCEPT) { if(pos <= 0) { left = node_handler::nil; this->merge(right, this->create(value_type{}, -pos), tree); } else if(tree->size <= pos) { right = node_handler::nil; this->merge(left, tree, this->create(value_type{}, pos - tree->size)); } else { this->_split(tree, pos, left, right); } } void merge(node_pointer& tree, const node_pointer& left, const node_pointer& right) noexcept(NO_EXCEPT) { if(left == node_handler::nil) { tree = right; this->push(tree); } else if(right == node_handler::nil) { tree = left; this->push(tree); } else { this->_merge(tree, left, right); tree->color = node_colors::BLACK; } this->pull(tree); } }; } // namespace internal template<std::integral SizeType = i64, class NodeHandler = uni::node_handlers::reusing<std::allocator<SizeType>>> struct red_black_tree_context { static constexpr bool LEAF_ONLY = true; template<class Derived, class ValueType = internal::dummy> using substance = internal::red_black_tree_impl<NodeHandler, Derived, SizeType, ValueType>; }; template<std::integral SizeType = i64, class Allocator = std::allocator<SizeType>> struct persistent_red_black_tree_context { static constexpr bool LEAF_ONLY = true; template<class Derived, class ValueType = internal::dummy> using substance = internal::red_black_tree_impl<uni::node_handlers::cloneable<Allocator>, Derived, SizeType, ValueType>; }; namespace pmr { template<std::integral SizeType = i64> using red_black_tree_context = uni::red_black_tree_context<SizeType, std::pmr::polymorphic_allocator<SizeType>>; template<std::integral SizeType = i64> using persistent_red_black_tree_context = uni::persistent_red_black_tree_context<SizeType, std::pmr::polymorphic_allocator<SizeType>>; } // namespace pmr } // namespace uni #line 2 "data_structure/removable_priority_queue.hpp" #line 8 "data_structure/removable_priority_queue.hpp" #line 12 "data_structure/removable_priority_queue.hpp" namespace uni { namespace internal { template<class T, class... Ts> concept can_removable_priority_queue = sizeof...(Ts) == 0 && requires (T pq, typename T::value_type v) { { pq.size() } -> std::same_as<typename T::size_type>; { pq.empty() } -> std::same_as<bool>; pq.top(); pq.pop(); pq.push(v); pq.emplace(v); }; } // namespace internal template<class... Ts> struct removable_priority_queue {}; template<class ValueType, class... Args> requires (!internal::can_removable_priority_queue<ValueType, Args...>) && requires () { typename std::priority_queue<ValueType, Args...>; } struct removable_priority_queue<ValueType, Args...> : removable_priority_queue<std::priority_queue<ValueType, Args...>> { using removable_priority_queue<std::priority_queue<ValueType, Args...>>::removable_priority_queue; }; template<internal::can_removable_priority_queue PriorityQueue> struct removable_priority_queue<PriorityQueue> : removable_priority_queue<PriorityQueue, internal::dummy> { using removable_priority_queue<PriorityQueue, internal::dummy>::removable_priority_queue; }; template< internal::can_removable_priority_queue PriorityQueue, class Multiset > struct removable_priority_queue<PriorityQueue, Multiset> : PriorityQueue { using base_type = PriorityQueue; using multiset_type = Multiset; using size_type = typename PriorityQueue::size_type; using value_type = typename PriorityQueue::value_type; using const_reference = typename PriorityQueue::const_reference; private: using self = removable_priority_queue<PriorityQueue, Multiset>; base_type _deleted; multiset_type _elements; static constexpr bool CHECK_EXISTANCE = !std::same_as<multiset_type, internal::dummy>; void _delete() noexcept(NO_EXCEPT) { while(!this->_deleted.empty() && this->_deleted.top() == this->base_type::top()) { this->base_type::pop(); this->_deleted.pop(); } } public: using base_type::base_type; size_type size() noexcept(NO_EXCEPT) { if constexpr(!self::CHECK_EXISTANCE) { assert(this->base_type::size() >= this->_deleted.size()); } return this->base_type::size() - this->_deleted.size(); } size_type empty() noexcept(NO_EXCEPT) { if constexpr(!self::CHECK_EXISTANCE) { assert(this->base_type::size() >= this->_deleted.size()); } return this->base_type::size() == this->_deleted.size(); } void push(const value_type& v) noexcept(NO_EXCEPT) { if constexpr(self::CHECK_EXISTANCE) this->_elements.insert(v); return this->base_type::push(v); } void push(value_type&& v) noexcept(NO_EXCEPT) { if constexpr(self::CHECK_EXISTANCE) this->_elements.insert(std::move(v)); return this->base_type::push(std::move(v)); } template<class... Args> decltype(auto) emplace(Args&&... args) noexcept(NO_EXCEPT) { if constexpr(self::CHECK_EXISTANCE) this->_elements.emplace(args...); return this->base_type::emplace(std::forward<Args>(args)...); } std::conditional_t<self::CHECK_EXISTANCE, bool, void> remove(const value_type& v) noexcept(NO_EXCEPT) { if constexpr(self::CHECK_EXISTANCE) { if(!this->_elements.contains(v)) return false; } this->_deleted.push(v); if constexpr(self::CHECK_EXISTANCE) return true; } std::conditional_t<self::CHECK_EXISTANCE, bool, void> remove(value_type&& v) noexcept(NO_EXCEPT) { if constexpr(self::CHECK_EXISTANCE) { if(!this->_elements.contains(v)) return false; } this->_deleted.push(std::move(v)); if constexpr(self::CHECK_EXISTANCE) return true; } template<class... Args> std::conditional_t<self::CHECK_EXISTANCE, bool, void> eliminate(Args&&... args) noexcept(NO_EXCEPT) { if constexpr(self::CHECK_EXISTANCE) { if(!this->_elements.contains({ args... })) return false; } this->_deleted.emplace(std::forward<Args>(args)...); if constexpr(self::CHECK_EXISTANCE) return true; } const_reference top() noexcept(NO_EXCEPT) { this->_delete(); return this->base_type::top(); } void pop() noexcept(NO_EXCEPT) { this->_delete(); this->base_type::pop(); } }; } // namespace uni #line 2 "data_structure/restorable_stack.hpp" #line 6 "data_structure/restorable_stack.hpp" #line 8 "data_structure/restorable_stack.hpp" namespace uni { template<class T, class ID = int, template<class,class> class storage = std::unordered_map> struct restorable_stack { using value_type = T; using key_type = ID; protected: struct node; using node_ptr = std::shared_ptr<node>; struct node { std::optional<value_type> val = std::nullopt; node_ptr parent; }; node_ptr _current; storage<key_type, node_ptr> _storage; public: restorable_stack() noexcept(NO_EXCEPT) { this->clear(); }; inline bool empty() const noexcept(NO_EXCEPT) { return !this->_current->val.has_value(); } inline bool stored(const key_type& x) const noexcept(NO_EXCEPT) { return this->_storage.count(x); } inline const value_type& top() const noexcept(NO_EXCEPT) { return this->_current->val.value(); } inline auto get() const noexcept(NO_EXCEPT) { return this->_current.val; } template<std::convertible_to<T> U = T> inline auto top_or(U &&v) const noexcept(NO_EXCEPT) { return this->_current->val.value_or(std::forward<U>(v)); } inline auto& push(const value_type& x) noexcept(NO_EXCEPT) { this->_current.reset(new node{ x, this->_current }); return *this; } inline auto& pop() noexcept(NO_EXCEPT) { this->_current = this->_current->parent; return *this; } inline auto& save(const key_type& x) noexcept(NO_EXCEPT) { this->_storage[x] = this->_current; return *this; } inline auto& load(const key_type& x) noexcept(NO_EXCEPT) { assert(this->stored(x)); this->_current = this->_storage[x]; return *this; } inline auto& clear() noexcept(NO_EXCEPT) { this->_current.reset(new node{}); return *this; } inline auto& load_or_clear(const key_type& x) noexcept(NO_EXCEPT) { if(this->stored(x)) this->load(x); else this->clear(); return *this; } }; } // namespace uni #line 2 "data_structure/segment_tree_rooter.hpp" #line 5 "data_structure/segment_tree_rooter.hpp" #line 9 "data_structure/segment_tree_rooter.hpp" namespace uni { template<std::integral SizeType> struct segment_tree_rooter { using size_type = SizeType; private: size_type _n = 0; public: segment_tree_rooter() noexcept = default; explicit segment_tree_rooter(const size_type n) noexcept(NO_EXCEPT) : _n(n) {}; inline size_type size() const noexcept(NO_EXCEPT) { return this->_n; } inline size_type allocated() const noexcept(NO_EXCEPT) { return (this->_n << 1) - 1; } template<std::invocable<size_type> F> void range_to_nodes(size_type l, size_type r, F&& f) noexcept(NO_EXCEPT) { l += this->_n; r += this->_n; while(l < r) { if(l & 1) f(l++ - 1); if(r & 1) f(--r - 1); l >>= 1; r >>= 1; } } size_type point_to_node(const size_type p) noexcept(NO_EXCEPT) { return this->_n + p - 1; } template<std::invocable<size_type> F> void point_to_path(size_type p, F&& f) noexcept(NO_EXCEPT) { p += this->_n; while(p > 0) f(p - 1), p >>= 1; } }; } #line 2 "data_structure/wavelet_matrix.hpp" #line 19 "data_structure/wavelet_matrix.hpp" #line 22 "data_structure/wavelet_matrix.hpp" #line 27 "data_structure/wavelet_matrix.hpp" #line 29 "data_structure/wavelet_matrix.hpp" #line 31 "data_structure/wavelet_matrix.hpp" #line 2 "iterable/compressed.hpp" #line 10 "iterable/compressed.hpp" #line 15 "iterable/compressed.hpp" #line 17 "iterable/compressed.hpp" namespace uni { template<class T, class Container = vector<internal::size_t>> struct compressed : Container { using size_type = internal::size_t; using value_type = T; std::vector<value_type> values; public: compressed() noexcept(NO_EXCEPT) = default; template<std::input_iterator I, std::sized_sentinel_for<I> S> compressed(I first, S last) noexcept(NO_EXCEPT) { this->values.assign(first, last); std::ranges::sort(ALL(this->values)); this->values.erase(std::unique(ALL(this->values)), std::ranges::end(this->values)); this->resize(std::ranges::distance(first, last)); { auto itr = std::ranges::begin(*this); auto e = first; for(; e!=last; ++itr, ++e) *itr = this->rank(*e); } } template<std::ranges::input_range R> explicit compressed(R&& range) noexcept(NO_EXCEPT) : compressed(ALL(range)) {} inline size_type rank_sup() const { return static_cast<size_type>(this->values.size()); } inline size_type rank(const value_type& val) const noexcept(NO_EXCEPT) { return static_cast<size_type>( std::ranges::distance(std::ranges::begin(this->values), std::ranges::lower_bound(this->values, val)) ); } inline size_type rank2(const value_type& val) const noexcept(NO_EXCEPT) { return static_cast<size_type>( std::ranges::distance(std::ranges::begin(this->values), std::ranges::upper_bound(this->values, val)) ) - 1; } inline value_type value(const size_type rank) const noexcept(NO_EXCEPT) { assert(0 <= rank && rank < this->rank_sup()); return this->values[rank]; } }; template<std::input_iterator I, std::sized_sentinel_for<I> S> explicit compressed(I, S) -> compressed<typename std::iterator_traits<I>::value_type>; template<std::ranges::input_range R> explicit compressed(R&&) -> compressed<typename std::ranges::range_value_t<R>>; } // namespace uni #line 33 "data_structure/wavelet_matrix.hpp" #line 35 "data_structure/wavelet_matrix.hpp" #line 38 "data_structure/wavelet_matrix.hpp" namespace uni { namespace internal { namespace wavelet_matrix_impl { // Thanks to: https://github.com/NyaanNyaan/library/blob/master/data-structure-2d/wavelet-matrix.hpp template<std::unsigned_integral T, class MapType> requires std::same_as<T, typename MapType::key_type> struct base { using size_type = internal::size_t; using impl_type = T; private: size_type _n; int _bits; std::vector<bit_vector> _index; std::vector<std::vector<impl_type>> _sum; MapType _first_pos; impl_type _max = 0; public: base() = default; template<std::ranges::input_range R> explicit base(R&& range) noexcept(NO_EXCEPT) : base(ALL(range)) {} template<std::input_iterator I, std::sentinel_for<I> S> base(I first, S last) noexcept(NO_EXCEPT) { this->build(first, last); } template<std::convertible_to<impl_type> U> base(const std::initializer_list<U>& init_list) noexcept(NO_EXCEPT) : base(ALL(init_list)) {} inline size_type size() const noexcept(NO_EXCEPT) { return this->_n; } inline size_type bits() const noexcept(NO_EXCEPT) { return this->_bits; } template<std::ranges::input_range R> inline void build(R&& range) noexcept(NO_EXCEPT) { this->build(ALL(range)); } template<std::input_iterator I, std::sized_sentinel_for<I> S> __attribute__((optimize("O3"))) void build(I first, S last) noexcept(NO_EXCEPT) { this->_n = static_cast<size_type>(std::ranges::distance(first, last)); this->_max = first == last ? -1 : *std::ranges::max_element(first, last); this->_bits = std::bit_width(this->_max + 1); this->_index.assign(this->_bits, this->_n); std::vector<impl_type> bit(first, last), nxt(this->_n); this->_sum.assign(this->_bits + 1, std::vector<impl_type>(this->_n + 1)); { size_type i = 0; for(auto itr=first; itr!=last; ++i, ++itr) { assert(*itr >= 0); this->_sum[this->_bits][i + 1] = this->_sum[this->_bits][i] + *itr; } } REPD(h, this->_bits) { std::vector<size_type> vals; for(size_type i = 0; i < this->_n; ++i) { if((bit[i] >> h) & 1) this->_index[h].set(i); } this->_index[h].build(); std::array<typename std::vector<impl_type>::iterator, 2> itrs{ std::ranges::begin(nxt), std::ranges::next(std::ranges::begin(nxt), this->_index[h].zeros()) }; REP(i, this->_n) *itrs[this->_index[h].get(i)]++ = bit[i]; REP(i, this->_n) this->_sum[h][i + 1] = this->_sum[h][i] + nxt[i]; std::swap(bit, nxt); } REPD(i, this->_n) this->_first_pos[bit[i]] = static_cast<MapType::mapped_type>(i); } protected: inline auto get(const size_type k) const noexcept(NO_EXCEPT) { return this->_sum[this->_bits][k + 1] - this->_sum[this->_bits][k]; } auto select(const impl_type& v, const size_type rank) const noexcept(NO_EXCEPT) { if(v > this->_max) return this->_n; if(not this->_first_pos.contains(v)) return this->_n; size_type pos = this->_first_pos.at(v) + rank; REP(h, this->_bits) { if(uni::bit(v, h)) pos = this->_index[h].select1(pos - this->_index[h].zeros()); else pos = this->_index[h].select0(pos); } return pos; } auto kth_smallest(size_type *const l, size_type *const r, size_type *const k) const noexcept(NO_EXCEPT) { impl_type val = 0; for(size_type h = this->_bits - 1; h >= 0; --h) { size_type l0 = this->_index[h].rank0(*l), r0 = this->_index[h].rank0(*r); if(*k < r0 - l0) { *l = l0, *r = r0; } else { *k -= r0 - l0; val |= impl_type{1} << h; *l += this->_index[h].zeros() - l0; *r += this->_index[h].zeros() - r0; } } return val; } inline auto kth_smallest(size_type l, size_type r, size_type k) const noexcept(NO_EXCEPT) { return this->kth_smallest(&l, &r, &k); } auto kth_smallest_index(size_type l, size_type r, size_type k) const noexcept(NO_EXCEPT) { const impl_type val = this->kth_smallest(&l, &r, &k); size_type left = 0; REPD(h, this->_bits) { if(uni::bit(val, h)) left = this->_index[h].rank1(left) + this->_index[h].zeros(); else left = this->_index[h].rank0(left); } return this->select(val, l + k - left); } inline auto kth_largest(const size_type l, const size_type r, const size_type k) const noexcept(NO_EXCEPT) { return this->kth_smallest(l, r, r - l - k - 1); } inline auto kth_largest_index(const size_type l, const size_type r, const size_type k) const noexcept(NO_EXCEPT) { return this->kth_smallest_index(l, r, r - l - k - 1); } inline auto succ0(const size_type l, const size_type r, const size_type h) const noexcept(NO_EXCEPT) { return std::make_pair(this->_index[h].rank0(l), this->_index[h].rank0(r)); } inline auto succ1(const size_type l, const size_type r, const size_type h) const noexcept(NO_EXCEPT) { const size_type l0 = this->_index[h].rank0(l); const size_type r0 = this->_index[h].rank0(r); const size_type vals = this->_index[h].zeros(); return std::make_pair(l + vals - l0, r + vals - r0); } impl_type sum_in_range( const size_type l, const size_type r, const impl_type& x, const impl_type& y, const impl_type& cur, const size_type bit ) const noexcept(NO_EXCEPT) { if(l == r) return 0; if(bit == -1) { if(x <= cur && cur <= y) return cur * (r - l); return 0; } const impl_type nxt = (impl_type{1} << bit) | cur; const impl_type ones = ((impl_type{1} << bit) - 1) | nxt; if(ones < x || y < cur) return 0; if(x <= cur && ones <= y) return this->_sum[bit + 1][r] - this->_sum[bit + 1][l]; const size_type l0 = this->_index[bit].rank0(l), r0 = this->_index[bit].rank0(r); const size_type l1 = l - l0, r1 = r - r0; return this->sum_in_range(l0, r0, x, y, cur, bit - 1) + this->sum_in_range(this->_index[bit].zeros() + l1, this->_index[bit].zeros() + r1, x, y, nxt, bit - 1); } inline auto sum_in_range(const size_type l, const size_type r, const impl_type& x, const impl_type& y) const noexcept(NO_EXCEPT) { return this->sum_in_range(l, r, x, y, 0, this->_bits - 1); } inline auto sum_under(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->sum_in_range(l, r, 0, v - 1); } inline auto sum_over(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->sum_in_range(l, r, v + 1, std::numeric_limits<impl_type>::max()); } inline auto sum_or_under(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->sum_in_range(l, r, 0, v); } inline auto sum_or_over(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->sum_in_range(l, r, v, std::numeric_limits<impl_type>::max()); } inline auto sum(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return this->_sum[this->_bits][r] - this->_sum[this->_bits][l]; } auto count_under(size_type l, size_type r, const impl_type& y) const noexcept(NO_EXCEPT) { if(y >= (impl_type{1} << this->_bits)) return r - l; size_type res = 0; REPD(h, this->_bits) { bool f = (y >> h) & 1; size_type l0 = this->_index[h].rank0(l), r0 = this->_index[h].rank0(r); if(f) { res += r0 - l0; l += this->_index[h].zeros() - l0; r += this->_index[h].zeros() - r0; } else { l = l0; r = r0; } } return res; } inline auto count_or_under(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->count_under(l, r, v + 1); } inline auto count_or_over(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return r - l - this->count_under(l, r, v); } inline auto count_over(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->count_or_over(l, r, v + 1); } inline auto count_in_range(const size_type l, const size_type r, const impl_type& x, const impl_type& y) const noexcept(NO_EXCEPT) { return this->count_or_under(l, r, y) - this->count_under(l, r, x); } inline auto count_equal_to(const size_type l, const size_type r, const impl_type& v) const noexcept(NO_EXCEPT) { return this->count_in_range(l, r, v, v); } inline std::optional<impl_type> next(const size_type l, const size_type r, const impl_type& v, const size_type k) const noexcept(NO_EXCEPT) { const size_type rank = this->count_under(l, r, v) + k; if(rank < 0 || rank >= r - l) return {}; return { this->kth_smallest(l, r, rank) }; } inline std::optional<impl_type> prev(const size_type l, const size_type r, const impl_type& v, const size_type k) const noexcept(NO_EXCEPT) { const size_type rank = this->count_over(l, r, v) + k; if(rank < 0 || rank >= r - l) return {}; return this->kth_largest(l, r, rank); } }; } // namespace wavelet_matrix_impl } // namespace internal template<std::integral T, template<class...> class MapTemplate = gnu::gp_hash_table> struct compressed_wavelet_matrix; template<std::integral T, template<class...> class MapTemplate = gnu::gp_hash_table> struct wavelet_matrix : internal::wavelet_matrix_impl::base<std::make_unsigned_t<T>, MapTemplate<std::make_unsigned_t<T>, u32>> { using value_type = T; using impl_type = std::make_unsigned_t<T>; using map_type = MapTemplate<impl_type, u32>; using size_type = internal::size_t; using compressed = compressed_wavelet_matrix<value_type, MapTemplate>; private: using base = internal::wavelet_matrix_impl::base<impl_type, map_type>; public: protected: inline size_type _positivize_index(const size_type p) const noexcept(NO_EXCEPT) { return p < 0 ? this->size() + p : p; } public: using base::base; inline bool empty() const noexcept(NO_EXCEPT) { return this->size() == 0; } inline value_type get(size_type p) const noexcept(NO_EXCEPT) { p = this->_positivize_index(p), assert(0 <= p && p < this->size()); return this->base::get(p); } inline auto operator[](const size_type p) const noexcept(NO_EXCEPT) { return this->get(p); } inline auto select(const value_type& v, const size_type p) const noexcept(NO_EXCEPT) { return this->base::select(v, p); } struct iterator; struct range_reference; template<uni::interval_notation rng = uni::interval_notation::right_open> inline auto range(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { if constexpr(rng == uni::interval_notation::right_open) return range_reference(this, l, r); if constexpr(rng == uni::interval_notation::left_open) return range_reference(this, l + 1, r + 1); if constexpr(rng == uni::interval_notation::open) return range_reference(this, l + 1, r); if constexpr(rng == uni::interval_notation::closed) return range_reference(this, l, r + 1); } inline auto range() const noexcept(NO_EXCEPT) { return range_reference(this, 0, this->size()); } inline auto operator()(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto subseq(const size_type p, const size_type c) const noexcept(NO_EXCEPT) { return range_reference(this, p, p+c); } inline auto subseq(const size_type p) const noexcept(NO_EXCEPT) { return range_reference(this, p, this->size()); } struct range_reference : internal::range_reference<const wavelet_matrix> { range_reference(const wavelet_matrix *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<const wavelet_matrix>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->size()); } inline auto get(const size_type k) const noexcept(NO_EXCEPT) { k = this->_super->_positivize_index(k); assert(0 <= k && k < this->size()); return this->_super->get(this->_begin + k); } inline auto operator[](const size_type k) const noexcept(NO_EXCEPT) { return this->get(k); } inline value_type kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { assert(0 <= k && k < this->size()); return this->_super->base::kth_smallest(this->_begin, this->_end, k); } inline auto kth_smallest_element(const size_type k) const noexcept(NO_EXCEPT) { if(k == this->size()) return this->end(); assert(0 <= k && k < this->size()); return std::ranges::next(this->_super->begin(), this->_super->base::kth_smallest_index(this->_begin, this->_end, k)); } inline value_type kth_largest(const size_type k) const noexcept(NO_EXCEPT) { assert(0 <= k && k < this->size()); return this->_super->base::kth_largest(this->_begin, this->_end, k); } inline auto kth_largest_element(const size_type k) const noexcept(NO_EXCEPT) { if(k == this->size()) return this->end(); assert(0 <= k && k < this->size()); return std::ranges::next(this->_super->begin(), this->_super->base::kth_largest_index(this->_begin, this->_end, k)); } inline auto min() const noexcept(NO_EXCEPT) { return this->kth_smallest(0); } inline auto max() const noexcept(NO_EXCEPT) { return this->kth_largest(0); } // (r-l)/2 th smallest (0-origin) inline auto median() const noexcept(NO_EXCEPT) { return this->kth_smallest(this->size() / 2); } inline value_type sum_in_range(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->_super->base::sum_in_range(this->_begin, this->_end, x, y); } inline value_type sum_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::sum_under(this->_begin, this->_end, v); } inline value_type sum_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::sum_over(this->_begin, this->_end, v); } inline value_type sum_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::sum_or_under(this->_begin, this->_end, v); } inline value_type sum_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::sum_or_over(this->_begin, this->_end, v); } inline value_type sum(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->_super->base::sum_in_range(this->_begin, this->_end, x, y); } inline value_type sum() const noexcept(NO_EXCEPT) { return this->_super->base::sum(this->_begin, this->_end); } template<comparison com> inline auto sum(const value_type& v) const noexcept(NO_EXCEPT) { if constexpr(com == comparison::under) return this->sum_under(v); if constexpr(com == comparison::over) return this->sum_over(v); if constexpr(com == comparison::or_under) return this->sum_or_under(v); if constexpr(com == comparison::or_over) return this->sum_or_over(v); assert(false); } inline auto count_in_range(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->_super->base::count_in_range(this->_begin, this->_end, x, y); } inline auto count_equal_to(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::count_equal_to(this->_begin, this->_end, v); } inline auto count_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::count_under(this->_begin, this->_end, v); } inline auto count_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::count_over(this->_begin, this->_end, v); } inline auto count_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::count_or_under(this->_begin, this->_end, v); } inline auto count_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_super->base::count_or_over(this->_begin, this->_end, v); } template<comparison com = comparison::equal_to> inline auto count(const value_type& v) const noexcept(NO_EXCEPT) { if constexpr(com == comparison::equal_to) return this->count_equal_to(v); if constexpr(com == comparison::under) return this->count_under(v); if constexpr(com == comparison::over) return this->count_over(v); if constexpr(com == comparison::or_under) return this->count_or_under(v); if constexpr(com == comparison::or_over) return this->count_or_over(v); assert(false); } inline auto next_element(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->kth_smallest_element(std::clamp(this->count_under(v) + k, size_type{ 0 }, this->size())); } inline auto prev_element(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->kth_largest_element(std::clamp(this->count_over(v) - k, size_type{ 0 }, this->size())); } inline std::optional<value_type> next(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->_super->base::next(this->_begin, this->_end, v, k); } inline std::optional<value_type> prev(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->_super->base::prev(this->_begin, this->_end, v, k); } }; inline auto kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_smallest(k); } inline auto kth_smallest_element(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_smallest_element(k); } inline auto kth_largest(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_largest(k); } inline auto kth_largest_element(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_largest_element(k); } inline auto min() const noexcept(NO_EXCEPT) { return this->range().kth_smallest(0); } inline auto max() const noexcept(NO_EXCEPT) { return this->range().kth_largest(0); } // (size)/2 th smallest (0-origin) inline auto median() const noexcept(NO_EXCEPT) { return this->range().median(); } inline auto sum_in_range(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->range().sum_in_range(x, y); } inline auto sum_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().sum_under(v); } inline auto sum_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().sum_over(v); } inline auto sum_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().sum_or_under(v); } inline auto sum_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().sum_or_over(v); } inline auto sum(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->range().sum_in_range(x, y); } inline auto sum() const noexcept(NO_EXCEPT) { return this->range().sum(); } template<comparison com> inline auto sum(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().template sum<com>(v); } inline auto count_in_range(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->range().count_in_range(x, y); } inline auto count_equal_to(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_equal_to(v); } inline auto count_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_under(v); } inline auto count_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_over(v); } inline auto count_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_or_under(v); } inline auto count_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_or_over(v); } template<comparison com = comparison::equal_to> inline auto count(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().template count<com>(v); } inline auto next_element(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().next_element(v); } inline auto prev_element(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().prev_element(v); } inline auto next(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->range().next(v, k); } inline auto prev(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->range().prev(v, k); } struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, const wavelet_matrix, const iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, this->size()); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } }; template<std::integral T, template<class...> class MapTemplate> struct compressed_wavelet_matrix : protected wavelet_matrix<u32, MapTemplate> { using value_type = T; using size_type = internal::size_t; protected: using core = wavelet_matrix<u32, MapTemplate>; using compresser = compressed<value_type, valarray<u32>>; compresser _comp; public: compressed_wavelet_matrix() = default; template<std::ranges::input_range R> explicit compressed_wavelet_matrix(R&& range) noexcept(NO_EXCEPT) : compressed_wavelet_matrix(ALL(range)) {} template<std::input_iterator I, std::sentinel_for<I> S> compressed_wavelet_matrix(I first, S last) noexcept(NO_EXCEPT) { this->build(first, last); } template<std::input_iterator I, std::sentinel_for<I> S> inline void build(I first, S last) noexcept(NO_EXCEPT) { this->_comp = compresser(first, last); this->core::build(ALL(this->_comp)); } inline auto get(const size_type k) const noexcept(NO_EXCEPT) { return this->_comp.value(this->core::get(k)); } inline auto operator[](const size_type k) const noexcept(NO_EXCEPT) { return this->_comp.value(this->core::get(k)); } struct iterator; struct range_reference; template<uni::interval_notation rng = uni::interval_notation::right_open> inline auto range(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { if constexpr(rng == uni::interval_notation::right_open) return range_reference(this, l, r); if constexpr(rng == uni::interval_notation::left_open) return range_reference(this, l + 1, r + 1); if constexpr(rng == uni::interval_notation::open) return range_reference(this, l + 1, r); if constexpr(rng == uni::interval_notation::closed) return range_reference(this, l, r + 1); } inline auto range() const noexcept(NO_EXCEPT) { return range_reference(this, 0, this->size()); } inline auto operator()(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return range_reference(this, l, r); } inline auto subseq(const size_type p, const size_type c) const noexcept(NO_EXCEPT) { return range_reference(this, p, p+c); } inline auto subseq(const size_type p) const noexcept(NO_EXCEPT) { return range_reference(this, p, this->size()); } struct range_reference : internal::range_reference<const compressed_wavelet_matrix> { range_reference(const compressed_wavelet_matrix *const super, const size_type l, const size_type r) noexcept(NO_EXCEPT) : internal::range_reference<const compressed_wavelet_matrix>(super, super->_positivize_index(l), super->_positivize_index(r)) { assert(0 <= this->_begin && this->_begin <= this->_end && this->_end <= this->_super->size()); } private: inline auto _range() const noexcept(NO_EXCEPT) { return this->_super->core::range(this->_begin, this->_end); } public: inline auto get(const size_type k) const noexcept(NO_EXCEPT) { return this->_super->_comp.value(this->_range().get(k)); } inline auto operator[](const size_type k) const noexcept(NO_EXCEPT) { return this->get(k); } inline auto kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { return this->_super->_comp.value(this->_range().kth_smallest(k)); } inline auto kth_smallest_element(const size_type k) const noexcept(NO_EXCEPT) { return std::ranges::next(this->_super->begin(), std::ranges::distance(this->_super->core::begin(), this->_range().kth_smallest_element(k))); } inline auto kth_largest(const size_type k) const noexcept(NO_EXCEPT) { return this->_super->_comp.value(this->_range().kth_largest(k));} inline auto kth_largest_element(const size_type k) const noexcept(NO_EXCEPT) { return std::ranges::next(this->_super->begin(), std::ranges::distance(this->_super->core::begin(), this->_range().kth_largest_element(k))); } inline auto min() const noexcept(NO_EXCEPT) { return this->kth_smallest(0); } inline auto max() const noexcept(NO_EXCEPT) { return this->kth_largest(0); } // (r-l)/2 th smallest (0-origin) inline auto median() const noexcept(NO_EXCEPT) { return this->kth_smallest(this->size() / 2); } inline auto count_in_range(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->_range().count_in_range(this->_super->_comp.rank(x), this->_super->_comp.rank2(y)); } inline size_type count_equal_to(const value_type& v) const noexcept(NO_EXCEPT) { const auto p = this->_super->_comp.rank(v); const auto q = this->_super->_comp.rank2(v); if(p != q) return 0; return this->_range().count_equal_to(p); } inline auto count_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_range().count_under(this->_super->_comp.rank(v)); } inline auto count_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_range().count_over(this->_super->_comp.rank2(v)); } inline auto count_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->_range().count_or_under(this->_super->_comp.rank2(v)); } inline auto count_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->_range().count_or_over(this->_super->_comp.rank(v)); } template<comparison com = comparison::equal_to> inline auto count(const value_type& v) const noexcept(NO_EXCEPT) { if constexpr(com == comparison::equal_to) return this->count_equal_to(v); if constexpr(com == comparison::under) return this->count_under(v); if constexpr(com == comparison::over) return this->count_over(v); if constexpr(com == comparison::or_under) return this->count_or_under(v); if constexpr(com == comparison::or_over) return this->count_or_over(v); assert(false); } inline auto next_element(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->kth_smallest_element(std::clamp(this->_range().count_under(this->_super->_comp.rank(v) + k), size_type{ 0 }, this->size())); } inline auto prev_element(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->kth_largest_element(std::clamp(this->_range().count_over(this->_super->_comp.rank2(v) + k), size_type{ 0 }, this->size())); } inline std::optional<value_type> next(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { const auto res = this->_range().next(this->_super->_comp.rank(v), k); if(res.has_value()) return this->_super->_comp.value(res.value()); return {}; } inline std::optional<value_type> prev(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { const auto res = this->_range().prev(this->_super->_comp.rank2(v), k); if(res.has_value()) return this->_super->_comp.value(res.value()); return {}; } }; inline auto kth_smallest(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_smallest(k); } inline auto kth_smallest_element(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_smallest_element(k); } inline auto kth_largest(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_largest(k); } inline auto kth_largest_element(const size_type k) const noexcept(NO_EXCEPT) { return this->range().kth_largest_element(k); } inline auto min() const noexcept(NO_EXCEPT) { return this->range().kth_smallest(0); } inline auto max() const noexcept(NO_EXCEPT) { return this->range().kth_largest(0); } inline auto median() const noexcept(NO_EXCEPT) { return this->range().median(); } inline auto count_in_range(const value_type& x, const value_type& y) const noexcept(NO_EXCEPT) { return this->range().count_in_range(x, y); } inline auto count_equal_to(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_equal_to(v); } inline auto count_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_under(v); } inline auto count_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_over(v); } inline auto count_or_under(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_or_under(v); } inline auto count_or_over(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().count_or_over(v); } template<comparison com = comparison::equal_to> inline auto count(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().template count<com>(v); } inline auto next_element(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().next_element(v); } inline auto prev_element(const value_type& v) const noexcept(NO_EXCEPT) { return this->range().prev_element(v); } inline auto next(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->range().next(v, k); } inline auto prev(const value_type& v, const size_type k = 0) const noexcept(NO_EXCEPT) { return this->range().prev(v, k); } struct iterator; protected: using iterator_interface = internal::container_iterator_interface<value_type, const compressed_wavelet_matrix, const iterator>; public: struct iterator : iterator_interface { using iterator_interface::iterator_interface; }; inline auto begin() const noexcept(NO_EXCEPT) { return iterator(this, 0); } inline auto end() const noexcept(NO_EXCEPT) { return iterator(this, this->size()); } inline auto rbegin() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() const noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } }; template<std::ranges::input_range R> explicit wavelet_matrix(R&&) -> wavelet_matrix<std::ranges::range_value_t<R>>; template<std::input_iterator I, std::sentinel_for<I> S> explicit wavelet_matrix(I, S) -> wavelet_matrix<std::iter_value_t<I>>; template<std::ranges::input_range R> explicit compressed_wavelet_matrix(R&&) -> compressed_wavelet_matrix<std::ranges::range_value_t<R>>; template<std::input_iterator I, std::sentinel_for<I> S> explicit compressed_wavelet_matrix(I, S) -> compressed_wavelet_matrix<std::iter_value_t<I>>; } // namespace uni #line 2 "include/geometries.hpp" #line 2 "geometry/arrow.hpp" #line 5 "geometry/arrow.hpp" #line 7 "geometry/arrow.hpp" #line 2 "geometry/point.hpp" #include <complex> #line 9 "geometry/point.hpp" #line 12 "geometry/point.hpp" #line 14 "geometry/point.hpp" #line 18 "geometry/point.hpp" #line 2 "numeric/float.hpp" #line 6 "numeric/float.hpp" #line 10 "numeric/float.hpp" namespace uni { template<class T> inline std::int32_t compare(const T x, const T y, const T tolerance) { if(x > y + tolerance) return 1; if(y > x + tolerance) return -1; return 0; } template<class T> inline std::int32_t compare(const T x, const T y = 0) { if constexpr(std::is_floating_point_v<T>) { return compare(x, y, max(1, x, y) * numeric_limits<T>::arithmetic_epsilon()); } else { if(x > y) return 1; if(x < y) return -1; return 0; } } } // namespace uni #line 2 "view/cyclic.hpp" #line 8 "view/cyclic.hpp" #line 12 "view/cyclic.hpp" #line 15 "view/cyclic.hpp" namespace uni { template<std::ranges::input_range View> requires std::ranges::view<View> struct cyclic_view : std::ranges::view_interface<cyclic_view<View>> { private: View _base; template<bool Const> using Base = internal::maybe_const_t<Const, View>; template<bool Const> struct iterator_tag {}; template<bool Const> requires std::ranges::forward_range<Base<Const>> struct iterator_tag<Const> { private: static constexpr auto _iterator_category() noexcept { using category = typename std::iterator_traits<std::ranges::iterator_t<Base<Const>>>::iterator_category; if constexpr(std::derived_from<category, std::random_access_iterator_tag>) return std::random_access_iterator_tag{}; else return category{}; } public: using iterator_category = decltype(_iterator_category()); }; public: template<bool> class iterator; constexpr explicit cyclic_view(View base) noexcept(NO_EXCEPT) : _base(std::move(base)) {} inline constexpr View base() const & noexcept(NO_EXCEPT) requires std::copy_constructible<View> { return this->_base; } inline constexpr View base() && noexcept(NO_EXCEPT) { return std::move(this->_base); } inline constexpr auto begin() noexcept(NO_EXCEPT) requires(!internal::simple_view<View>) { return iterator<false>(this, std::ranges::begin(this->_base)); } inline constexpr auto begin() const noexcept(NO_EXCEPT) requires std::ranges::range<const View> { return iterator<true>(this, std::ranges::begin(this->_base)); } inline constexpr auto end() noexcept(NO_EXCEPT) requires(!internal::simple_view<View>) { return std::unreachable_sentinel; } inline constexpr auto end() const noexcept(NO_EXCEPT) requires std::ranges::range<const View> { return std::unreachable_sentinel; } }; template<class Range> cyclic_view(Range &&) -> cyclic_view<std::views::all_t<Range>>; template<std::ranges::input_range View> requires std::ranges::view<View> template<bool Const> struct cyclic_view<View>::iterator : iterator_tag<Const> { private: using Parent = internal::maybe_const_t<Const, cyclic_view>; using Base = cyclic_view::Base<Const>; std::ranges::iterator_t<Base> _current = std::ranges::iterator_t<Base>(); std::ranges::iterator_t<Base> _begin = std::ranges::iterator_t<Base>(); std::ranges::sentinel_t<Base> _end = std::ranges::sentinel_t<Base>(); constexpr iterator(Parent *const parent, const std::ranges::iterator_t<Base> current) noexcept(NO_EXCEPT) : _current(std::move(current)), _begin(std::ranges::begin(parent->_base)), _end(std::ranges::end(parent->_base)) {} friend cyclic_view; public: using difference_type = std::ranges::range_difference_t<Base>; using value_type = std::ranges::range_value_t<Base>; using iterator_concept = typename internal::iterator_concept<Base>; private: difference_type _index = 0; public: iterator() noexcept(NO_EXCEPT) requires std::default_initializable<std::ranges::iterator_t<Base>> = default; constexpr iterator(iterator<!Const> itr) noexcept(NO_EXCEPT) requires Const && std::convertible_to<std::ranges::iterator_t<View>, std::ranges::iterator_t<Base>> && std::convertible_to<std::ranges::sentinel_t<View>, std::ranges::sentinel_t<Base>> : _current(std::move(itr._current)), _begin(std::move(itr._begin)), _end(std::move(itr._end)), _index(std::move(itr._index)) {} inline constexpr std::ranges::iterator_t<Base> base() && noexcept(NO_EXCEPT) { return std::move(this->_current); } inline constexpr const std::ranges::iterator_t<Base> &base() const & noexcept { return this->_current; } inline constexpr decltype(auto) operator*() const noexcept(NO_EXCEPT) { return *this->_current; } inline constexpr iterator& operator++() noexcept(NO_EXCEPT) { assert(this->_current != _end); ++this->_index; ++this->_current; if(this->_current == this->_end) this->_current = this->_begin; return *this; } inline constexpr void operator++(int) noexcept(NO_EXCEPT) { ++*this; } inline constexpr iterator operator++(int) noexcept(NO_EXCEPT) requires std::ranges::forward_range<Base> { const auto res = *this; ++*this; return res; } inline constexpr iterator& operator--() noexcept(NO_EXCEPT) requires std::ranges::bidirectional_range<Base> { --this->_index; if(this->_current == this->_begin) this->_current = std::ranges::prev(this->_end); else --this->_current; return *this; } inline constexpr iterator operator--(int) noexcept(NO_EXCEPT) requires std::ranges::bidirectional_range<Base> { const auto res = *this; --*this; return res; } inline constexpr iterator& operator+=(const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { this->_index += diff; if(diff > 0) { auto missing = std::ranges::advance(this->_current, diff, this->_end); if constexpr(std::ranges::sized_range<Base>) missing %= std::ranges::distance(this->_begin, this->_end); while(this->_current == this->_end) { this->_current = this->_begin; missing = std::ranges::advance(this->_current, missing, this->_end); } } else if(diff < 0) { auto missing = std::ranges::advance(this->_current, diff, this->_begin); if constexpr(std::ranges::sized_range<Base>) missing %= std::ranges::distance(this->_begin, this->_end); while(missing < 0) { this->_current = this->_end; missing = std::ranges::advance(this->_current, missing, this->_begin); } } return *this; } inline constexpr iterator& operator-=(const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { return *this += -diff; } inline constexpr decltype(auto) operator[](const difference_type diff) const noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { return *(*this + diff); } friend inline constexpr bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::equality_comparable<std::ranges::iterator_t<Base>> { return lhs._index == rhs._index; } friend inline constexpr auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> && std::three_way_comparable<std::ranges::iterator_t<Base>> { return rhs._index <=> lhs._index; } friend inline constexpr iterator operator+(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { auto res = itr; res += diff; return res; } friend inline constexpr iterator operator+(const difference_type diff, const iterator& itr) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { return itr + diff; } friend inline constexpr iterator operator-(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { auto res = itr; res -= diff; return res; } friend inline constexpr const difference_type operator-(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::iterator_t<Base>, std::ranges::iterator_t<Base>> { return lhs._index - rhs._index; } friend inline constexpr std::ranges::range_rvalue_reference_t<Base> iter_move(const iterator& itr) noexcept(NO_EXCEPT) { return std::ranges::iter_move(itr._current); } friend inline constexpr void iter_swap(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::indirectly_swappable<std::ranges::iterator_t<Base>> { std::swap(lhs._index, rhs._index); std::ranges::iter_swap(lhs._current, rhs._current); } }; namespace views { namespace internal { template<class Range> concept can_cyclic_view = requires { cyclic_view(std::declval<Range>()); }; } struct Cyclic : adaptor::range_adaptor_closure<Cyclic> { template<std::ranges::viewable_range Range> requires internal::can_cyclic_view<Range> inline constexpr auto operator() [[nodiscard]] (Range &&res) const { return cyclic_view(std::forward<Range>(res)); } // using adaptor::range_adaptor_closure<Cyclic>::operator(); // static constexpr int arity = 1; // static constexpr bool has_simple_call_op = true; }; inline constexpr Cyclic cyclic; } // namespace views } // namespace uni namespace std::ranges { template<class View> inline constexpr bool enable_borrowed_range<uni::cyclic_view<View>> = enable_borrowed_range<View>; } // namespace std::ranges #line 22 "geometry/point.hpp" namespace uni { template <class T> struct point { using value_type = T; private: value_type _x, _y; public: constexpr point() : point(0, 0) {} constexpr point(const T& x, const T& y) noexcept(NO_EXCEPT) : _x(x), _y(y) {} template<class U> constexpr point(const point<U>& p) noexcept(NO_EXCEPT) : _x(p.x()), _y(p.y()) {}; template<class U> constexpr point& operator=(const point<U>& p) & noexcept(NO_EXCEPT) { if(&p != this) this->_x = p._x, this->_y = p._y; return *this; }; inline constexpr auto& x() noexcept(NO_EXCEPT) { return this->_x; } inline constexpr auto& y() noexcept(NO_EXCEPT) { return this->_y; } inline constexpr const auto& x() const noexcept(NO_EXCEPT) { return this->_x; } inline constexpr const auto& y() const noexcept(NO_EXCEPT) { return this->_y; } constexpr auto& rotate_quarter() noexcept(NO_EXCEPT) { const auto x = this->_x - this->_y; const auto y = this->_x + this->_y; this->_x = std::move(x), this->_y = std::move(y); return *this; } constexpr auto& operator+=(const point& v) noexcept(NO_EXCEPT) { this->_x += v._x, this->_y += v._y; return *this; } constexpr auto& operator-=(const point& v) noexcept(NO_EXCEPT) { this->_x -= v._x, this->_y -= v._y; return *this; } constexpr auto& operator+=(const value_type& v) noexcept(NO_EXCEPT) { this->_x += v, this->_y += v; return *this; } constexpr auto& operator-=(const value_type& v) noexcept(NO_EXCEPT) { this->_x -= v, this->_y -= v; return *this; } constexpr auto& operator*=(const value_type& v) noexcept(NO_EXCEPT) { this->_x *= v, this->_y *= v; return *this; } constexpr auto& operator/=(const value_type& v) noexcept(NO_EXCEPT) { this->_x /= v, this->_y /= v; return *this; } friend inline constexpr auto operator+(const point& p) noexcept(NO_EXCEPT) { return { +p._x, +p._y }; } friend inline constexpr auto operator-(const point& p) noexcept(NO_EXCEPT) { return { -p._x, -p._y }; } friend inline constexpr auto operator+(point a, const point& b) noexcept(NO_EXCEPT) { return a += b; } friend inline constexpr auto operator-(point a, const point& b) noexcept(NO_EXCEPT) { return a -= b; } friend constexpr auto operator*(const point& a, const point& b) noexcept(NO_EXCEPT) { return a._x * b._x + a._y * b._y; } friend inline constexpr auto operator+(point a, const value_type& b) noexcept(NO_EXCEPT) { return a += b; } friend inline constexpr auto operator-(point a, const value_type& b) noexcept(NO_EXCEPT) { return a -= b; } friend inline constexpr auto operator*(point a, const value_type& b) noexcept(NO_EXCEPT) { return a *= b; } friend inline constexpr auto operator/(point a, const value_type& b) noexcept(NO_EXCEPT) { return a /= b; } friend inline constexpr auto operator+(const value_type& a, point b) noexcept(NO_EXCEPT) { return b += a; } friend inline constexpr auto operator-(const value_type& a, point b) noexcept(NO_EXCEPT) { return b += a; } friend inline constexpr auto operator*(const value_type& a, point b) noexcept(NO_EXCEPT) { return b *= a; } friend inline constexpr auto operator/(const value_type& a, point b) noexcept(NO_EXCEPT) { return b /= a; } friend inline constexpr bool operator==(const point& a, const point& b) noexcept(NO_EXCEPT) { return compare(a._x, b._x) == 0 and compare(a._y, b._y) == 0; } friend inline constexpr bool operator!=(const point& a, const point& b) noexcept(NO_EXCEPT) { return !(a == b); } friend inline constexpr bool operator<(const point& a, const point& b) noexcept(NO_EXCEPT) { return compare(a._x, b._x) != 0 ? compare(a._x, b._x) < 0 : compare(a._y, b._y) < 0; } friend inline constexpr bool operator>(const point& a, const point& b) noexcept(NO_EXCEPT) { return compare(a._x, b._x) != 0 ? compare(a._x, b._x) > 0 : compare(a._y, b._y) > 0; } friend inline constexpr bool operator<=(const point& a, const point& b) noexcept(NO_EXCEPT) { return !(a > b); } friend inline constexpr bool operator>=(const point& a, const point& b) noexcept(NO_EXCEPT) { return !(a < b); } auto _debug() const { return std::make_pair(this->_x, this->_y); } }; template<size_t I, class T> inline const auto& get(const point<T>& p) noexcept(NO_EXCEPT) { if constexpr(I == 0) { return p.x(); } else if constexpr(I == 1) { return p.y(); } else static_assert(uni::internal::EXCEPTION_ON_VALUE<I>); } template<size_t I, class T> inline auto& get(point<T>& p) noexcept(NO_EXCEPT) { if constexpr(I == 0) return p.x(); else if constexpr(I == 1) return p.y(); else static_assert(internal::EXCEPTION_ON_VALUE<I>); } } // namespace uni namespace std { template<class T> struct tuple_size<uni::point<T>> : integral_constant<size_t,2> {}; template<size_t I, class T> struct tuple_element<I,uni::point<T>> { using type = typename uni::point<T>::value_type; }; template<class T> constexpr auto norm(const uni::point<T>& v) noexcept(NO_EXCEPT) { return v.x() * v.x() + v.y() * v.y(); } template<class T> constexpr auto abs(const uni::point<T>& v) noexcept(NO_EXCEPT) { if constexpr(is_floating_point_v<T>) { return static_cast<T>(std::abs(std::complex<T>(v.x(), v.y()))); } else { return static_cast<T>(sqrt(norm(v))); } } template<class T> constexpr auto arg(const uni::point<T>& v) noexcept(NO_EXCEPT) { return static_cast<T>(std::arg(std::complex<T>(v.x(), v.y()))); } template<class T, class C, class S> auto& operator>>(basic_istream<C, S>& in, uni::point<T>& v) noexcept(NO_EXCEPT) { T x, y; in >> x >> y; v = { x, y }; return in; } template<class T, class C, class S> auto& operator<<(basic_ostream<C, S>& out, const uni::point<T>& v) noexcept(NO_EXCEPT) { out << v.x() << " " << v.y(); return out; } } // namespace std namespace uni { template<class T> constexpr auto distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) { return std::abs(a - b); } template<class T> constexpr auto squared_distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) { return std::norm(a - b); } template<class T> constexpr auto manhattan_distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) { return std::abs(a.x() - b.x()) + std::abs(a.y() - b.y()); } template<class T> constexpr auto chebyshev_distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) { return std::max(std::abs(a.x() - b.x()), std::abs(a.y() - b.y())); } template<class T> constexpr auto dot(point<T> a, point<T> b, const point<T>& o = point<T>()) noexcept(NO_EXCEPT) { a -= o, b -= o; return a * b; } template<class T> constexpr auto cross(point<T> a, point<T> b, const point<T>& o = point<T>()) noexcept(NO_EXCEPT) { a -= o, b -= o; return a.x() * b.y() - a.y() * b.x(); } template<class T, class Angle = T> constexpr point<T> rotate(const point<T>& p, const Angle angle) noexcept(NO_EXCEPT) { return { std::cos(angle) * p.x() - std::sin(angle) * p.y(), std::sin(angle) * p.x() + std::cos(angle) * p.y() }; } template<class T, class Angle = T> constexpr auto rotate(const point<T>& p, const point<T>& q, const Angle angle) noexcept(NO_EXCEPT) { return rotate(p - q, angle) + q; } template<class T> inline constexpr auto relation(const point<T>& p, const point<T>& q) noexcept(NO_EXCEPT) { return relation<T>({ 0, 0 }, p, q); } template<class T> auto to_degree(const T& radian) { return radian * 180 / PI<T>; } template<class T> auto to_radian(const T& degree) { return degree * PI<T> / 180; } } // namespace uni #line 2 "geometry/line.hpp" #line 7 "geometry/line.hpp" #line 11 "geometry/line.hpp" namespace uni { template<class Point> struct line { using point_type = Point; using value_type = typename point_type::value_type; protected: point_type _p0, _p1; public: constexpr void normalize() noexcept(NO_EXCEPT) { if(this->_p0 > this->_p1) std::swap(this->_p0, this->_p1); } constexpr line() noexcept = default; constexpr line(const point_type& p0, const point_type& p1) noexcept(NO_EXCEPT) : _p0(p0), _p1(p1) { this->normalize(); } constexpr line(const value_type a, const value_type b, const value_type c) noexcept(NO_EXCEPT) { if(compare(a) == 0) this->_p0 = { 0, c / b }, this->_p1 = { 1, c / b }; else if(compare(b) == 0) this->_p0 = { c / a, 0 }, this->_p1 = { c / a, 1 }; else this->_p0 = { 0, c / b }, this->_p1 = { c / a, 0 }; this->normalize(); } inline constexpr auto& p0() noexcept(NO_EXCEPT) { return this->_p0; } inline constexpr auto& p1() noexcept(NO_EXCEPT) { return this->_p1; } inline constexpr const auto& p0() const noexcept(NO_EXCEPT) { return this->_p0; } inline constexpr const auto& p1() const noexcept(NO_EXCEPT) { return this->_p1; } constexpr auto vertices() noexcept(NO_EXCEPT) { return std::tie(this->_p0, this->_p1); } const constexpr auto vertices() const noexcept(NO_EXCEPT) { return std::make_pair(std::cref(this->_p0), std::cref(this->_p1)); } constexpr const auto to_vector() const noexcept(NO_EXCEPT) { return this->_p1 - this->_p0; } constexpr const auto length() const noexcept(NO_EXCEPT) { return uni::distance(this->_p0, this->_p1); } constexpr const auto squared_length() const noexcept(NO_EXCEPT) { return uni::squared_distance(this->_p0, this->_p1); } constexpr const auto midpoint() const noexcept(NO_EXCEPT) { return tuple_sum(this->vertices()) / 2; } constexpr auto projection(const point_type& p) noexcept(NO_EXCEPT) { const auto q = this->p0() - this->p1(); const auto s1 = (p - this->p0()) * q / std::norm(q); return this->p0() + q * s1; } constexpr auto reflection(const point_type& p) noexcept(NO_EXCEPT) { return p + (this->projection(p) - p) * 2; } // implemented in geometry/basic.hpp inline constexpr auto relation(const point_type& p) noexcept(NO_EXCEPT); auto _debug() const { return std::make_pair(this->_p0, this->_p1); } }; template<size_t I, class Point> inline const auto& get(const line<Point>& ln) noexcept(NO_EXCEPT) { if constexpr(I == 0) { return ln.p0(); } else if constexpr(I == 1) { return ln.p1(); } else static_assert(uni::internal::EXCEPTION_ON_VALUE<I>); } template<size_t I, class Point> inline auto& get(line<Point>& ln) noexcept(NO_EXCEPT) { if constexpr(I == 0) return ln.p0(); else if constexpr(I == 1) return ln.p1(); else static_assert(uni::internal::EXCEPTION_ON_VALUE<I>); } } // namespace uni namespace std { template<class Point> struct tuple_size<uni::line<Point>> : integral_constant<size_t, 2> {}; template<size_t I, class Point> struct tuple_element<I, uni::line<Point>> { using type = typename uni::line<Point>::value_type; }; template<class Point, class C, class S> auto& operator>>(basic_istream<C, S>& in, uni::line<Point>& v) noexcept(NO_EXCEPT) { Point x, y; in >> x >> y; v = { x, y }; return in; } template<class Point, class C, class S> auto& operator<<(basic_ostream<C, S>& out, const uni::line<Point>& v) noexcept(NO_EXCEPT) { out << v.p0() << " " << v.p1(); return out; } } // namespace std namespace uni { template<class Point> bool parallel(const line<Point>& p, const line<Point>& q) noexcept(NO_EXCEPT) { return compare(p.to_vector() * q.to_vector()) == 0; } template<class Point> bool orthogonal(const line<Point>& p, const line<Point>& q) noexcept(NO_EXCEPT) { return compare(cross(p.to_vector(), q.to_vector())) == 0; } template<class Point> constexpr std::optional<Point> intersection(const line<Point>& s, const line<Point>& t) noexcept(NO_EXCEPT) { using value_type = typename Point::value_type; const Point p = s.to_vector(), q = t.to_vector(); const value_type d0 = cross(p, q); const value_type d1 = cross(p, s.p1() - t.p0()); if(compare(d0) == 0 and compare(d1) == 0) return {}; return t.p0() + q * (d1 / d0); } namespace internal { template<class T> constexpr positional_relation relation( const line<point<T>>& ln, const point<T>& p, T *const _al = nullptr, T *const _bl = nullptr ) noexcept(NO_EXCEPT) { const point<T> a = ln.to_vector(); const point<T> b = p - ln.p0(); T al = std::norm(a), bl = std::norm(b); if(_al) *_al = al; if(_bl) *_bl = bl; const T s1 = al * bl; const T dot = a * b; if(compare(s1, dot * dot) != 0) return positional_relation::out; return positional_relation::in; } } // namespace internal template<class Point> inline constexpr auto line<Point>::relation(const Point& p) noexcept(NO_EXCEPT) { return internal::relation(*this, p); } template<class Point> auto distance(const line<Point>& ln, const Point& p) noexcept(NO_EXCEPT) { return std::abs(cross(ln.p1(), p, ln.p0())) / distance(ln.p1(), ln.p0()); } template<class Point> inline auto distance(const Point& p, const line<Point>& ln) noexcept(NO_EXCEPT) { return distance(ln, p); } template<class Point> auto squared_distance(const line<Point>& ln, const Point& p) noexcept(NO_EXCEPT) { const auto r = cross(ln.p1(), p, ln.p0()); return r * r / squared_distance(ln.p1(), ln.p0()); } template<class Point> inline auto squared_distance(const Point& p, const line<Point>& ln) noexcept(NO_EXCEPT) { return squared_distance(ln, p); } } // namespace uni #line 2 "geometry/segment.hpp" #line 5 "geometry/segment.hpp" #line 7 "geometry/segment.hpp" #line 10 "geometry/segment.hpp" namespace uni { template<class Point> struct segment : line<Point> { using point_type = Point; using value_type = typename point_type::value_type; constexpr segment() noexcept = default; constexpr segment(const point_type& p0, const point_type& p1) noexcept(NO_EXCEPT) : line<Point>(p1) { this->_normalize(); } constexpr segment(const line<point_type>& ln) noexcept(NO_EXCEPT) : segment(ln.p0(), ln.p1()) {} constexpr auto relation(const point_type& p) noexcept(NO_EXCEPT); }; template<bool ALLOW_END_POINT, class Point> bool intersecting(const segment<Point>& s0, const segment<Point>& s1) noexcept(NO_EXCEPT) { const auto cp0 = cross(s0.p1(), s1.p0(), s0.p0()); const auto cp1 = cross(s0.p1(), s1.p1(), s0.p0()); const auto cp2 = cross(s1.p1(), s0.p0(), s1.p0()); const auto cp3 = cross(s1.p1(), s0.p1(), s1.p0()); if(compare(cp0) == 0 and compare(cp1) == 0 and compare(cp2) == 0 and compare(cp3) == 0) { return std::max(s0.p0(), s1.p0()) <= std::min(s0.p1(), s1.p1()); } if constexpr(ALLOW_END_POINT) return compare(cp0 * cp1) <= 0 and compare(cp2 * cp3) <= 0; else return compare(cp0 * cp1) < 0 and compare(cp2 * cp3) < 0; } template<class Point> bool intersecting(const segment<Point>& s0, const segment<Point>& s1) noexcept(NO_EXCEPT) { return intersecting<true>(s0, s1); } template<class Point> inline constexpr std::optional<Point> intersection(const segment<Point>& s0, const segment<Point>& s1) noexcept(NO_EXCEPT) { if(!intersecting(s0, s1)) return {}; return intersection(line<Point>(s0), line<Point>(s1)); } template<class Point> constexpr auto segment<Point>::relation(const Point& p) noexcept(NO_EXCEPT) { if(p == this->_p0 or p == this->_p1) return positional_relation::on; typename Point::value_type al, bl; if(internal::relation(p, *this, &al, &bl) == positional_relation::out) { return positional_relation::out; }; const auto comp = compare(al, bl); if(comp < 0) return positional_relation::out; if(comp > 0) return positional_relation::in; assert(false); } template<class Point> double distance(const segment<Point>& s0, const segment<Point> &s1) { if(intersecting(s0, s1)) return 0; return min( distance(s0, s1.p0()), distance(s0, s1.p1()), distance(s1, s0.p0()), distance(s1, s0.p1()) ); } template<class Point> double squared_distance(const segment<Point>& s0, const segment<Point> &s1) { if(intersecting(s0, s1)) return 0; return min( squared_distance(s0, s1.p0()), squared_distance(s0, s1.p1()), squared_distance(s1, s0.p0()), squared_distance(s1, s0.p1()) ); } template<class Point> auto distance(const segment<Point>& seg, const Point& p) noexcept(NO_EXCEPT) { if(compare(dot(seg.p1(), p, seg.p0())) < 0) return distance(p, seg.p0()); if(compare(dot(seg.p0(), p, seg.p1())) < 0) return distance(p, seg.p1()); return distance(line<Point>(seg), p); } template<class Point> inline auto distance(const Point& p, const segment<Point>& seg) noexcept(NO_EXCEPT) { return distance(seg, p); } template<class Point> auto squared_distance(const segment<Point>& seg, const Point& p) noexcept(NO_EXCEPT) { if(compare(dot(seg.p1(), p, seg.p0())) < 0) return squared_distance(p, seg.p0()); if(compare(dot(seg.p0(), p, seg.p1())) < 0) return squared_distance(p, seg.p1()); return squared_distance(line<Point>(seg), p); } template<class Point> inline auto squared_distance(const Point& p, const segment<Point>& seg) noexcept(NO_EXCEPT) { return squared_distance(seg, p); } } // namespace uni #line 11 "geometry/arrow.hpp" namespace uni { template<class Point> struct arrow : segment<Point> { using point_type = Point; using value_type = typename point_type::value_type; constexpr arrow() noexcept = default; // p0 -> p1 constexpr arrow(const point_type& p0, const point_type& p1) noexcept(NO_EXCEPT) { this->_p0 = p0, this->_p1 = p1; } constexpr auto relation(const point_type& p) noexcept(NO_EXCEPT); }; template<class Point> constexpr auto arrow<Point>::relation(const Point& p) noexcept(NO_EXCEPT) { if(this->_p0 == p || this->_p1 == p) return positional_relation::on; const auto q0 = this->_p1 - this->_p0, q1 = p - this->_p0; const auto comp_qr = compare(cross(q0, q1)); if(comp_qr > 0) return positional_relation::counter_clockwise; if(comp_qr < 0) return positional_relation::clockwise; if(compare(q0 * q1) < 0) return positional_relation::backward; if(compare(std::norm(q0), std::norm(q1)) < 0) return positional_relation::forward; return positional_relation::in; } } // namespace uni namespace std { template<class Point, class C, class S> auto& operator>>(basic_istream<C, S>& in, uni::arrow<Point>& v) noexcept(NO_EXCEPT) { Point x, y; in >> x >> y; v = { x, y }; return in; } } // namespace std #line 2 "geometry/circle.hpp" #line 5 "geometry/circle.hpp" #line 9 "geometry/circle.hpp" #line 12 "geometry/circle.hpp" namespace uni { template<class Point> struct circle { using point_type = Point; using value_type = typename point_type::value_type; protected: point_type _c; value_type _r2; public: circle() noexcept = default; static constexpr auto raw(const point_type& c, const value_type& r2) noexcept(NO_EXCEPT) { circle res; res._c = c, res._r2 = r2; return res; } constexpr circle(const point_type& c, const value_type& r) noexcept(NO_EXCEPT) : _c(c), _r2(r * r) {} explicit constexpr circle(const value_type& r) noexcept(NO_EXCEPT) : _c({ 0, 0 }), _r2(r * r) {} constexpr circle(const point_type& p0, const point_type& p1, const point_type& p2) noexcept(NO_EXCEPT) : circle(triangle(p0, p1, p2)) {}; explicit constexpr circle(const segment<point_type>& seg) noexcept(NO_EXCEPT) : _c(seg.midpoint()), _r2(seg.squared_length() / 4) {}; inline constexpr auto& center() noexcept(NO_EXCEPT) { return this->_c; } inline constexpr const auto& center() const noexcept(NO_EXCEPT) { return this->_c; } inline auto radius() const noexcept(NO_EXCEPT) { return static_cast<value_type>(std::sqrt(this->_r2)); } inline constexpr auto& squared_radius() noexcept(NO_EXCEPT) { return this->_r2; } inline constexpr const auto& squared_radius() const noexcept(NO_EXCEPT) { return this->_r2; } constexpr auto relation(const point_type& p) noexcept(NO_EXCEPT) { const auto dist = uni::squared_distance(this->_c, p); const auto comp = compare(dist, this->_r2); if(comp > 0) return positional_relation::out; if(comp < 0) return positional_relation::in; return positional_relation::on; } auto _debug() const noexcept(NO_EXCEPT) { return std::make_pair(this->center(), this->radius()); } }; template<class Point> int count_common_tangent(const circle<Point>& c0, const circle<Point>& c1) { const auto dist = distance(c0.center(), c1.center()); const auto l0 = c0.radius() + c1.radius(); const auto l1 = std::abs(c0.radius() - c1.radius()); if(compare(dist, l0) > 0) return 4; if(compare(dist, l0) == 0) return 3; if(compare(dist, l1) == 0) return 1; if(compare(dist, l1) < 0) return 0; return 2; } template<class Point> auto relation(const circle<Point>& c0, const circle<Point>& c1) { const auto t = count_common_tangent(c0, c1); switch(t) { case 0: return uni::positional_relation::included; case 1: return uni::positional_relation::inscribed; case 2: return uni::positional_relation::intersecting; case 3: return uni::positional_relation::circumscribed; case 4: return uni::positional_relation::distant; } assert(false); } } // namespace uni #line 2 "geometry/convex_hull.hpp" #line 7 "geometry/convex_hull.hpp" #line 10 "geometry/convex_hull.hpp" #line 2 "geometry/polygon.hpp" #line 6 "geometry/polygon.hpp" #line 9 "geometry/polygon.hpp" #line 13 "geometry/polygon.hpp" #line 16 "geometry/polygon.hpp" namespace uni { template<class Point, class Container = vector<Point>> struct polygon : Container { using point_type = Point; using container_type = Container; using value_type = point_type::value_type; using size_type = Container::size_type; static_assert(std::same_as<typename container_type::value_type, point_type>); using container_type::container_type; auto doubled_area() noexcept(NO_EXCEPT) { const auto n = std::ranges::ssize(*this); const auto view = uni::views::cyclic(*this); value_type res = 0; REP(i, n) res += cross(view[i], view[i + 1]); return res; } inline auto area() noexcept(NO_EXCEPT) { return this->doubled_area() / 2; } template<bool = true> bool is_convex() noexcept(NO_EXCEPT); // implemented in geometry/convex_hull.hpp template<bool ALLOW_LINE = true, bool LEAVE_MARGIN = false> auto convex_hull() noexcept(NO_EXCEPT); }; template<class Point, class Container> struct convex_polygon : polygon<Point, Container> { using polygon<Point, Container>::polygon; }; namespace internal { template<bool ALLOW_LINE, std::ranges::sized_range R> requires std::ranges::forward_range<R> bool is_convex(R&& range) noexcept(NO_EXCEPT) { const auto n = std::ranges::size(range); const auto view = uni::views::cyclic(range); auto itr0 = std::ranges::begin(view); auto itr1 = std::ranges::next(itr0); auto itr2 = std::ranges::next(itr1); REP(n) { const auto r = arrow(*(itr0++), *(itr1++)).relation(*(itr2++)); if constexpr(ALLOW_LINE) { if(r == positional_relation::clockwise) return false; } else { if(r != positional_relation::anti_clockwise) return false; } } return true; } } // namespace internal template<class Point, class Container> template<bool ALLOW_LINE> inline bool polygon<Point, Container>::is_convex() noexcept(NO_EXCEPT) { return ( internal::is_convex<ALLOW_LINE>(*this) || internal::is_convex<ALLOW_LINE>(std::views::reverse(*this)) ); } } // namespace uni #line 13 "geometry/convex_hull.hpp" namespace uni { template<class Point, class Container> template<bool ALLOW_LINE, bool LEAVE_MARGIN> auto polygon<Point, Container>::convex_hull() noexcept(NO_EXCEPT) { auto remove = [&](const point_type& p, const point_type& q, const point_type& r) -> bool { if constexpr(ALLOW_LINE) { return compare(cross(p, q, r)) < 0; } else { return compare(cross(p, q, r)) <= 0; } }; std::vector<point_type> points(ALL(*this)); const auto n = std::ranges::ssize(points); using ssize_type = std::remove_const_t<decltype(n)>; std::ranges::sort(points); polygon res(2 * n); ssize_type k = 0; for(ssize_type i = 0; i < n; res[k++] = points[i++]) { while(k >= 2 && remove(points[i], res[k - 2], res[k - 1])) --k; } for(auto i = n - 2, t = k + 1; i >= 0; res[k++] = points[i--]) { while(k >= t && remove(points[i], res[k - 2], res[k - 1])) --k; } if constexpr(LEAVE_MARGIN) res.resize(k); else res.resize(k - 1); return res; } } // namespace uni #line 2 "geometry/triangle.hpp" #line 7 "geometry/triangle.hpp" #line 11 "geometry/triangle.hpp" #line 14 "geometry/triangle.hpp" namespace uni { template<class Point> struct triangle { using point_type = Point; using value_type = typename point_type::value_type; private: point_type _p0, _p1, _p2; protected: constexpr void _normalize() noexcept(NO_EXCEPT) { std::array<point_type,3> vs = { this->_p0, this->_p1, this->_p2 }; std::ranges::sort(vs); std::tie(this->_p0, this->_p1, this->_p2) = std::tie(vs[0], vs[1], vs[2]); } public: constexpr triangle() noexcept(NO_EXCEPT) {} constexpr triangle(const point_type& p0, const point_type& p1, const point_type& p2 = point_type()) noexcept(NO_EXCEPT) : _p0(p0), _p1(p1), _p2(p2) { this->_normalize(); } inline constexpr auto& p0() noexcept(NO_EXCEPT) { return this->_p0; } inline constexpr auto& p1() noexcept(NO_EXCEPT) { return this->_p1; } inline constexpr auto& p2() noexcept(NO_EXCEPT) { return this->_p2; } inline constexpr const auto& p0() const noexcept(NO_EXCEPT) { return this->_p0; } inline constexpr const auto& p1() const noexcept(NO_EXCEPT) { return this->_p1; } inline constexpr const auto& p2() const noexcept(NO_EXCEPT) { return this->_p2; } inline constexpr auto vertices() noexcept(NO_EXCEPT) { return std::tie(this->_p0, this->_p1, this->_p2); } inline constexpr auto vertices() const noexcept(NO_EXCEPT) { return std::make_tuple(std::cref(this->_p0), std::cref(this->_p1), std::cref(this->_p2)); } constexpr const auto signed_area() const noexcept(NO_EXCEPT) { return cross(this->_p0, this->_p1, this->_p2) / 2; } inline constexpr const auto area() const noexcept(NO_EXCEPT) { return std::abs(this->signed_area()); } constexpr auto distances() const noexcept(NO_EXCEPT) { return std::make_tuple( uni::distance(this->_p1, this->_p2), uni::distance(this->_p2, this->_p0), uni::distance(this->_p0, this->_p1) ); } constexpr auto squared_distances() const noexcept(NO_EXCEPT) { return std::make_tuple( uni::squared_distance(this->_p1, this->_p2), uni::squared_distance(this->_p2, this->_p0), uni::squared_distance(this->_p0, this->_p1) ); } constexpr auto angles() const noexcept(NO_EXCEPT) { const auto [ d0, d1, d2 ] = this->distances(); return std::make_tuple( std::acos((d1 * d1 + d2 * d2 - d0 * d0) / (2 * d1 * d2)), std::acos((d2 * d2 + d0 * d0 - d1 * d1) / (2 * d2 * d0)), std::acos((d0 * d0 + d1 * d1 - d2 * d2) / (2 * d0 * d1)) ); } constexpr point_type barycenter() const noexcept(NO_EXCEPT) { return tuple_sum(this->vertices()) / 3; } constexpr auto circumcenter() const noexcept(NO_EXCEPT) { const auto [ d0, d1, d2 ] = this->squared_distances(); const auto t0 = d0 * (d1 + d2 - d0); const auto t1 = d1 * (d2 + d0 - d1); const auto t2 = d2 * (d0 + d1 - d2); return (t0 * this->_p0 + t1 * this->_p1 + t2 * this->_p2) / (t0 + t1 + t2); } constexpr auto incenter() const noexcept(NO_EXCEPT) { const auto [ d0, d1, d2 ] = this->distances(); return (d0 * this->_p0 + d1 * this->_p1 + d2 * this->_p2) / (d0 + d1 + d2); } constexpr auto orthocenter() const noexcept(NO_EXCEPT) { return tuple_sum(this->vertices()) - 2 * this->circumcenter(); } constexpr triangle excenters() const noexcept(NO_EXCEPT) { const auto [ d0, d1, d2 ] = this->distances(); return { (d1 * this->_p1 + d2 * this->_p2 - d0 * this->_p0) / (d1 + d2 - d0), (d2 * this->_p1 + d0 * this->_p2 - d1 * this->_p0) / (d2 + d0 - d1), (d0 * this->_p1 + d1 * this->_p2 - d2 * this->_p0) / (d0 + d1 - d2) }; } // implemented in geometry/basic.hpp constexpr auto circumcircle() const noexcept(NO_EXCEPT); constexpr auto incircle() const noexcept(NO_EXCEPT); auto _debug() const noexcept(NO_EXCEPT) { return std::make_tuple(this->_p0, this->_p1, this->_p2); } }; template<size_t I, class T> inline const auto& get(const triangle<T>& t) noexcept(NO_EXCEPT) { if constexpr(I == 0) { return t.p0(); } else if constexpr(I == 1) { return t.p1(); } else if constexpr(I == 2) { return t.p2(); } else static_assert(internal::EXCEPTION_ON_VALUE<I>); } template<size_t I, class T> inline auto& get(triangle<T>& t) noexcept(NO_EXCEPT) { if constexpr(I == 0) return t.p0(); else if constexpr(I == 1) return t.p1(); else if constexpr(I == 2) return t.p2(); else static_assert(internal::EXCEPTION_ON_VALUE<I>); } } // namespace uni namespace std { template<class T> struct tuple_size<uni::triangle<T>> : integral_constant<size_t,3> {}; template<size_t I, class T> struct tuple_element<I,uni::triangle<T>> { using type = typename uni::triangle<T>::value_type; }; template<class T, class C, class S> auto& operator>>(basic_istream<C, S>& in, uni::triangle<T>& v) noexcept(NO_EXCEPT) { typename uni::triangle<T>::point_type p, q, r; in >> p >> q >> r; v = { p, q, r }; return in; } } // namespace std namespace uni { template<class> struct circle; template<class Point> constexpr auto triangle<Point>::incircle() const noexcept(NO_EXCEPT) { const auto p = this->incenter(); return circle<Point>::raw(p, squared_distance(p, line(this->_p0, this->_p1))); } template<class Point> constexpr auto triangle<Point>::circumcircle() const noexcept(NO_EXCEPT) { const auto p = this->circumcenter(); return circle<Point>::raw(p, squared_distance(p, this->_p0)); } } // namespace uni #line 2 "include/graph_theory.hpp" #line 2 "graph/centroid_decomposition.hpp" #line 6 "graph/centroid_decomposition.hpp" #line 2 "structure/graph.hpp" #line 8 "structure/graph.hpp" #line 12 "structure/graph.hpp" #line 16 "structure/graph.hpp" #line 21 "structure/graph.hpp" #line 2 "structure/grid.hpp" #line 12 "structure/grid.hpp" #line 16 "structure/grid.hpp" #line 19 "structure/grid.hpp" #line 21 "structure/grid.hpp" #line 24 "structure/grid.hpp" namespace uni { namespace internal { namespace grid_impl { template<class T> struct container_base { using value_type = T; using size_type = internal::size_t; private: size_type _h, _w; protected: inline void _validate_index(__attribute__ ((unused)) const size_type i, __attribute__ ((unused)) const size_type j) const noexcept(NO_EXCEPT) { assert(0 <= i and i < this->height()); assert(0 <= j and j < this->width()); } inline size_type _positivize_row_index(const size_type x) const noexcept(NO_EXCEPT) { return x < 0 ? this->height() + x : x; } inline size_type _positivize_col_index(const size_type x) const noexcept(NO_EXCEPT) { return x < 0 ? this->width() + x : x; } public: container_base() = default; container_base(const size_type h, const size_type w) noexcept(NO_EXCEPT) : _h(h), _w(w) {} void resize(const size_type h, const size_type w) noexcept(NO_EXCEPT) { this->_h = h, this->_w = w; } inline size_type height() const noexcept(NO_EXCEPT) { return this->_h; } inline size_type width() const noexcept(NO_EXCEPT) { return this->_w; } inline size_type id(const size_type i, const size_type j) const noexcept(NO_EXCEPT) { const size_type _i = this->_positivize_row_index(i); const size_type _j = this->_positivize_col_index(j); this->_validate_index(_i, _j); return _i * this->width() + _j; } inline size_type id(const std::pair<size_type,size_type>& p) const noexcept(NO_EXCEPT) { return this->id(p.first, p.second); } inline std::pair<size_type,size_type> pos(const size_type id) const noexcept(NO_EXCEPT) { return { id / this->width(), id % this->width() }; } }; template<class Base> struct regular_container : Base, container_base<typename Base::value_type::value_type> { using row_type = typename Base::value_type; using value_type = typename row_type::value_type; using size_type = internal::size_t; explicit regular_container(const size_type n = 0) noexcept(NO_EXCEPT) : regular_container(n, n) {} regular_container(const size_type h, const size_type w, const value_type &val = value_type()) noexcept(NO_EXCEPT) : Base(h, row_type(w, val)), container_base<value_type>(h, w) {} regular_container(const std::initializer_list<row_type> init_list) noexcept(NO_EXCEPT) : Base(init_list) { const auto rows = std::ranges::ssize(init_list); const size_type first_cols = init_list.begin()->size(); if constexpr (DEV_ENV) { ITR(init_row, init_list) assert((size_type)init_row.size() == first_cols); } this->container_base<value_type>::resize(rows, first_cols); } inline void assign(const regular_container &source) noexcept(NO_EXCEPT) { this->resize(source.height(), source.width()); this->Base::assign(ALL(source)); } inline void assign(const size_type h, const size_type w, const value_type &val = value_type()) noexcept(NO_EXCEPT) { this->container_base<value_type>::resize(h, w); this->Base::resize(h); ITRR(row, *this) row.assign(w, val); } inline void resize(const size_type h, const size_type w) noexcept(NO_EXCEPT) { this->container_base<value_type>::resize(h, w); this->Base::resize(h); ITRR(row, *this) row.resize(w); } inline auto& operator()(const size_type i, const size_type j) noexcept(NO_EXCEPT) { const size_type _i = this->_positivize_row_index(i); const size_type _j = this->_positivize_col_index(j); this->_validate_index(_i, _j); return (*this)[_i][_j]; } inline const auto& operator()(const size_type i, const size_type j) const noexcept(NO_EXCEPT) { const size_type _i = this->_positivize_row_index(i); const size_type _j = this->_positivize_col_index(j); this->_validate_index(_i, _j); return (*this)[_i][_j]; } inline auto& operator()(const std::pair<size_type,size_type>& p) noexcept(NO_EXCEPT) { return this->operator()(p.first, p.second); } inline const auto& operator()(const std::pair<size_type,size_type>& p) const noexcept(NO_EXCEPT) { return this->operator()(p.first, p.second); } }; template<class Base> struct unfolded_container : Base, container_base<typename Base::value_type> { using value_type = typename Base::value_type; using size_type = internal::size_t; explicit unfolded_container(size_type n = 0) noexcept(NO_EXCEPT) : unfolded_container(n, n) {} unfolded_container(const size_type h, const size_type w, const value_type &val = value_type()) noexcept(NO_EXCEPT) : Base(h * w, val), container_base<value_type>(h, w) {} unfolded_container(std::initializer_list<std::initializer_list<value_type>> init_list) noexcept(NO_EXCEPT) { const auto rows = std::ranges::ssize(init_list); const auto first_cols = std::ranges::ssize(std::ranges::begin(init_list)); this->resize(rows, first_cols); { size_type index = 0; for( auto itr = std::ranges::begin(init_list), itr_end = std::ranges::end(init_list); itr!=itr_end; ++itr ) { assert((size_type)itr->size() == first_cols); for(auto v=itr->begin(), v_end=itr->end(); v!=v_end; ++v) (*this)[index++] = *v; } } } inline void assign(const unfolded_container &source) noexcept(NO_EXCEPT) { this->resize(source.height(), source.width()); this->Base::assign(ALL(source)); } inline void assign(const size_type h, const size_type w, const value_type &val = value_type()) noexcept(NO_EXCEPT) { this->container_base<value_type>::resize(h, w); this->Base::assign(h * w, val); } inline void resize(const size_type h, const size_type w) noexcept(NO_EXCEPT) { this->container_base<value_type>::resize(h, w); this->Base::resize(h * w); } inline value_type& operator()(const size_type i, const size_type j) noexcept(NO_EXCEPT) { const size_type _i = this->_positivize_row_index(i); const size_type _j = this->_positivize_col_index(j); return this->operator[](this->id(_i, _j)); } inline value_type& operator()(const std::pair<size_type,size_type>& p) noexcept(NO_EXCEPT) { return this->operator()(this->id(p.first, p.second)); } inline const value_type& operator()(const std::pair<size_type,size_type>& p) const noexcept(NO_EXCEPT) { return this->operator()(this->id(p.first, p.second)); } }; } // namespace grid_impl template<class Container> struct grid_core : Container { using Container::Container; using value_type = Container::value_type; using size_type = internal::size_t; enum class invert_direction { vertical, horizontal }; enum class rotate_direction { counter_clockwise, clockwise }; inline bool is_valid(const size_type i, const size_type j) const noexcept(NO_EXCEPT) { return 0 <= i and i < this->height() and 0 <= j and j < this->width(); } inline bool is_valid(const std::pair<size_type, size_type>& p) const noexcept(NO_EXCEPT) { return this->is_valid(p.first, p.second); } template<std::input_iterator I, std::sentinel_for<I> S> inline auto vicinities(const size_type i, const size_type j, I dirs_first, S dirs_last) const noexcept(NO_EXCEPT) { std::vector<std::pair<size_type, size_type>> res; REP(itr, dirs_first, dirs_last) { const size_type ii = i + itr->first, jj = j + itr->second; if(this->is_valid(ii, jj)) res.emplace_back(ii, jj); } return res; } template<class I, class C> inline auto vicinities(const std::pair<size_type, size_type>& p, const C dirs) const noexcept(NO_EXCEPT) { return this->vicinities(p.first, p.second, ALL(dirs)); } inline auto vicinities4(const size_type i, const size_type j) const noexcept(NO_EXCEPT) { return this->vicinities(i, j, ALL(DIRS4)); } inline auto vicinities4(const std::pair<size_type, size_type>& p) const noexcept(NO_EXCEPT) { return this->vicinities(p.first, p.second, ALL(DIRS4)); } inline auto vicinities8(const size_type i, const size_type j) const noexcept(NO_EXCEPT) { return this->vicinities(i, j, ALL(DIRS8)); } inline auto vicinities8(const std::pair<size_type, size_type>& p) const noexcept(NO_EXCEPT) { return this->vicinities(p.first, p.second, ALL(DIRS8)); } template<invert_direction DIRECTION = invert_direction::vertical> inline grid_core& invert() noexcept(NO_EXCEPT) { grid_core res(this->height(), this->width()); REP(i, this->height()) REP(j, this->width()) { if constexpr (DIRECTION == invert_direction::vertical) { res(i,j) = (*this)(this->height()-i-1,j); } else { res(i,j) = (*this)(i, this->width()-j-1); } } this->assign(res); return *this; } template<rotate_direction DIRECTION = rotate_direction::clockwise> inline grid_core& rotate(const size_type k) noexcept(NO_EXCEPT) { grid_core res = *this; REP(i, k) { res = res.rotate<DIRECTION>(); } this->assign(res); return *this; } template<rotate_direction DIRECTION = rotate_direction::clockwise> inline grid_core& rotate() noexcept(NO_EXCEPT) { grid_core res(this->width(), this->height()); REP(i, this->width()) REP(j, this->height()) { if constexpr (DIRECTION == rotate_direction::clockwise) { res(i,j) = (*this)(this->height()-j-1,i); } else { res(i,j) = (*this)(j,this->width()-i-1); } } this->assign(res); return *this; } inline grid_core& transpose() noexcept(NO_EXCEPT) { grid_core res(this->width(), this->height()); REP(i, this->width()) REP(j, this->height()) { res(i,j) = (*this)(j,i); } this->assign(res); return *this; } }; } // namespace internal template<class T, class row_type = vector<T>, class Base = vector<row_type>> using grid = internal::grid_core<internal::grid_impl::regular_container<Base>>; template<class T, class row_type = valarray<T>, class Base = vector<row_type>> using valgrid = internal::grid_core<internal::grid_impl::regular_container<Base>>; template<class T, class Base = vector<T>> using unfolded_grid = internal::grid_core<internal::grid_impl::unfolded_container<Base>>; template<class T, class Base = valarray<T>> using unfolded_valgrid = internal::grid_core<internal::grid_impl::unfolded_container<Base>>; } // namespace uni #line 24 "structure/graph.hpp" #line 26 "structure/graph.hpp" #line 2 "internal/auto_holder.hpp" #line 5 "internal/auto_holder.hpp" #line 9 "internal/auto_holder.hpp" #line 11 "internal/auto_holder.hpp" namespace uni { namespace internal { namespace auto_holder_impl { template<class T, bool DYNAMIC, class = std::enable_if_t<std::is_integral_v<T> && not DYNAMIC>> constexpr int _holder_type(resolving_rank<2>) { return 0; } template<class T, bool> constexpr auto _holder_type(resolving_rank<1>) -> decltype(std::unordered_set<T>(), 0){ return 1; } template<class T, bool> constexpr int _holder_type(resolving_rank<0>) { return 2; } template<class T, bool DYNAMIC = false> constexpr int holder_type = _holder_type<T,DYNAMIC>(resolving_rank<10>{}); template<class,class,int> struct holder {}; template<class T, class U> struct holder<T, U, 0> : vector<U> { using vector<U>::vector; }; template<class T, class U> struct holder<T, U, 1> : gp_hash_table<T, U> { using gp_hash_table<T, U>::gp_hash_table; template<class V> inline void assign(const internal::size_t, const V& v) { this->set_default(v); } }; template<class T, class U> struct holder<T, U, 2> : map<T, U> { using map<T, U>::map; template<class V> inline void assign(const internal::size_t, const V& v) { this->set_default(v); } }; } // namespace auto_holder_impl } // namespace internal template<class T, class U> struct auto_holder : internal::auto_holder_impl::holder<T,U,internal::auto_holder_impl::holder_type<T>> { using internal::auto_holder_impl::holder<T,U,internal::auto_holder_impl::holder_type<T>>::holder; }; template<class T, class U> struct dynamic_auto_holder : internal::auto_holder_impl::holder<T,U,internal::auto_holder_impl::holder_type<T,true>> { using internal::auto_holder_impl::holder<T,U,internal::auto_holder_impl::holder_type<T,true>>::holder; }; } // namespace uni #line 28 "structure/graph.hpp" namespace uni { namespace internal { namespace graph_impl { template<class Node,class Cost> struct edge { private: inline static internal::size_t unique() noexcept(NO_EXCEPT) { static internal::size_t id = 0; return id++; } public: using cost_type = Cost; using node_type = Node; using size_type = internal::size_t; const size_type id = unique(); const node_type from, to; const Cost cost; const size_type index = 0; edge(const node_type u, const node_type v, const Cost w = 1, const size_type i = 0) noexcept(NO_EXCEPT) : from(u), to(v), cost(w), index(i) {} operator node_type() const noexcept(NO_EXCEPT) { return this->to; } inline node_type opposite(const node_type v) const noexcept(NO_EXCEPT) { if(this->from == v) return this->to; if(this->to == v) return this->from; assert(false); } auto _debug() const { return std::make_tuple(index, from, to, cost); }; friend bool operator==(const edge& lhs, const edge& rhs) noexcept(NO_EXCEPT) { return lhs.id == rhs.id; } friend bool operator!=(const edge& lhs, const edge& rhs) noexcept(NO_EXCEPT) { return lhs.id != rhs.id; } }; template<class NodeType, class CostType, class EdgeCollector> struct regular_base : EdgeCollector { using EdgeCollector::EdgeCollector; using size_type = internal::size_t; using node_type = NodeType; using cost_type = CostType; inline size_type size() const noexcept(NO_EXCEPT) { return static_cast<size_type>(this->EdgeCollector::size()); } }; template<class NodeType, class CostType, class Map> struct virtual_base : Map { public: using size_type = internal::size_t; using node_type = NodeType; using cost_type = CostType; protected: size_type _n = 0; public: template<class F> explicit virtual_base(const size_type n, F&& f) noexcept(NO_EXCEPT) : Map(std::forward<F>(f)), _n(n) {} inline size_type size() const noexcept(NO_EXCEPT) { return this->_n; } }; template<class NodeType, class CostType, template<class...> class Container> struct regular_core : regular_base<NodeType,CostType,Container<vector<internal::graph_impl::edge<NodeType,CostType>>>> { using size_type = internal::size_t; using node_type = NodeType; using cost_type = CostType; using edge_type = typename internal::graph_impl::edge<node_type,cost_type>; enum class edge_kind { undirected, directed }; private: using base = regular_base<NodeType,CostType,Container<vector<edge_type>>>; size_type _directed_edge_count = 0, _undirected_edge_count = 0; Container<edge_type> _edges; Container<size_type> _out_degs, _in_degs; protected: inline void _add_edge(const size_type u, const size_type v, const cost_type w, const size_type k) noexcept(NO_EXCEPT) { this->operator[](u).emplace_back(u, v, w, k); ++_out_degs[u], ++_in_degs[v]; ++this->_directed_edge_count; } public: explicit regular_core() noexcept(NO_EXCEPT) : base() {} explicit regular_core(const size_type n = 0) noexcept(NO_EXCEPT) : base(n), _out_degs(n), _in_degs(n) {} auto& clear() noexcept(NO_EXCEPT) { this->_directed_edge_count = 0, this->_undirected_edge_count = 0; this->base::clear(), this->_edges.clear(); this->_out_degs.clear(), this->_in_degs.clear(); return *this; } auto& resize(const size_type n) noexcept(NO_EXCEPT) { this->base::resize(n), this->_out_degs.resize(n), this->_in_degs.resize(n); return *this; } inline const auto& edges() const noexcept(NO_EXCEPT) { return this->_edges; } inline const auto& edge(const size_type k) const noexcept(NO_EXCEPT) { return this->_edges[k]; } inline const auto& degrees() const noexcept(NO_EXCEPT) { return this->_in_degs; } inline const auto& degree(const size_type k) const noexcept(NO_EXCEPT) { return this->_in_degs[k]; } inline const auto& in_degrees() const noexcept(NO_EXCEPT) { return this->_in_degs; } inline const auto& in_degree(const size_type k) const noexcept(NO_EXCEPT) { return this->_in_degs[k]; } inline const auto& out_degrees() const noexcept(NO_EXCEPT) { return this->_out_degs; } inline const auto& out_degree(const size_type k) const noexcept(NO_EXCEPT) { return this->_out_degs[k]; } inline size_type directed_edges_count() const noexcept(NO_EXCEPT) { return this->_directed_edge_count; } template<class R = valgrid<bool>> auto make_has_edges() const noexcept(NO_EXCEPT) { R res(this->size(), this->size(), false); REP(i, this->size()) ITR(j, this->operator[](i)) res[i][j] = true; return res; } template<bool SELF_ZERO = true, class T = cost_type, class R = valgrid<T>> auto make_initial_distance_matrix() const noexcept(NO_EXCEPT) { R res(this->size(), this->size(), numeric_limits<T>::arithmetic_infinity()); if constexpr(SELF_ZERO) REP(i, this->size()) res[i][i] = 0; REP(i, this->size()) ITR(j, this->operator[](i)) res[i][j] = j.cost; return res; } template<bool SELF_ZERO = true, class T = cost_type, class R = valgrid<T>> auto make_distance_matrix() const noexcept(NO_EXCEPT) { R res = this->make_initial_distance_matrix<SELF_ZERO,T,R>(); REP(k, this->size()) REP(i, this->size()) REP(j, this->size()) { chmin(res[i][j], res[i][k] + res[k][j]); } return res; } template<edge_kind EDGE_TYPE = edge_kind::directed> auto add_edge(const node_type u, const node_type v, const cost_type w = 1) noexcept(NO_EXCEPT) { assert(0 <= u and u < this->size()), assert(0 <= v and v < this->size()); const size_type k = this->edges().size(); this->_edges.emplace_back(u, v, w, k); this->_add_edge(u, v, w, k); if constexpr(EDGE_TYPE == edge_kind::undirected) this->_add_edge(v, u, w, k); return k; } inline auto add_edge_bidirectionally(const node_type u, const node_type v, const cost_type w = 1) noexcept(NO_EXCEPT) { return this->add_edge<edge_kind::undirected>(u, v, w); } template<bool WEIGHTED = false, bool ONE_ORIGIN = true, const edge_kind EDGE_TYPE = edge_kind::directed, class Stream = input_adaptor<>> void read(const size_type edges, Stream *const ist = &_input) noexcept(NO_EXCEPT) { REP(edges) { node_type u, v; cost_type w = 1; *ist >> u >> v; if(ONE_ORIGIN) --u, --v; if(WEIGHTED) *ist >> w; this->add_edge<EDGE_TYPE>(u, v, w); } } template<bool WEIGHTED = false, bool ONE_ORIGIN = true, class Stream = input_adaptor<>> void read_bidirectionally(const size_type edges, Stream *const ist = &_input) noexcept(NO_EXCEPT) { REP(edges) { node_type u, v; cost_type w = 1; *ist >> u >> v; if(ONE_ORIGIN) --u, --v; if(WEIGHTED) *ist >> w; this->add_edge<edge_kind::undirected>(u, v, w); } } }; template<class Graph> struct mixin : Graph { using Graph::Graph; using size_type = typename Graph::size_type; using node_type = typename Graph::node_type; using cost_type = typename Graph::cost_type; inline size_type vertices() const noexcept(NO_EXCEPT) { return static_cast<size_type>(this->Graph::size()); } public: // graph/shortest_path.hpp template<item_or_convertible_range<node_type> Source, class Dist, class Prev = std::nullptr_t> void shortest_path_without_cost(Source&&, Dist *const, Prev *const = nullptr, const node_type& = -1, const node_type& = -2) const noexcept(NO_EXCEPT); template<item_or_convertible_range<node_type> Source> auto shortest_path_without_cost(Source&&) const noexcept(NO_EXCEPT); // graph/dijkstra.hpp template<item_or_convertible_range<node_type> Source, class Dist, class Prev = std::nullptr_t> void shortest_path_with_01cost(Source&&, Dist *const, Prev *const = nullptr, const node_type& = -1, const node_type& = -2) const noexcept(NO_EXCEPT); template<item_or_convertible_range<node_type> Source> auto shortest_path_with_01cost(Source&&) const noexcept(NO_EXCEPT); // graph/dijkstra.hpp template<item_or_convertible_range<node_type> Source, class Dist, class Prev = std::nullptr_t> void shortest_path_with_cost(Source&&, Dist *const, Prev *const = nullptr, const node_type& = -1, const node_type& = -2) const noexcept(NO_EXCEPT); template<item_or_convertible_range<node_type> Source> auto shortest_path_with_cost(Source&&) const noexcept(NO_EXCEPT); // graph/topological_sort.hpp bool sort_topologically(vector<node_type> *const ) const noexcept(NO_EXCEPT); bool sort_topologically() const noexcept(NO_EXCEPT); // graph/topological_sort.hpp template<class> bool sort_topologically_with_priority(vector<node_type> *const) const noexcept(NO_EXCEPT); template<class> bool sort_topologically_with_priority() const noexcept(NO_EXCEPT); // graph/minimum_paph_cover.hpp size_type minimum_paph_cover_size_as_dag() const noexcept(NO_EXCEPT); // graph/spanning_tree_cost.hpp auto minimum_spanning_tree(mixin *const = nullptr) const noexcept(NO_EXCEPT); // graph/spanning_tree_cost.hpp auto maximum_spanning_tree(mixin *const = nullptr) const noexcept(NO_EXCEPT); // graph/reachability.hpp template<std::ranges::sized_range R> auto test_reachability(R&&) const noexcept(NO_EXCEPT); // graph/connected_components.hpp disjoint_set components() const noexcept(NO_EXCEPT); // graph/connected_components.hpp bool is_bipartite() const noexcept(NO_EXCEPT); // graph/connected_components.hpp template<class Colors> bool is_bipartite(Colors *const) const noexcept(NO_EXCEPT); // graph/parse_grid.hpp template<bool = false, class G, class U = char> void parse_grid(const G&, U = '.') noexcept(NO_EXCEPT); // graph/manhattan_minimum_spanning_tree.hpp template< std::input_iterator I0, std::input_iterator I1, std::sentinel_for<I0> S0, std::sentinel_for<I1> S1 > cost_type build_manhattan_mst(I0, S0, I1, S1) noexcept(NO_EXCEPT); }; } // namespace graph_impl } // namespace internal template<class Cost = std::int64_t, class Node = internal::size_t, template<class...> class Container = vector> struct graph : internal::graph_impl::mixin<internal::graph_impl::regular_core<Node, Cost, Container>> { private: using base = internal::graph_impl::mixin<internal::graph_impl::regular_core<Node, Cost, Container>>; public: using size_type = typename base::size_type; using node_type = typename base::node_type; using edge = typename internal::graph_impl::edge<node_type,Cost>; explicit graph(const size_type n = 0) noexcept(NO_EXCEPT) : base(n) {} }; template<class Node = internal::size_t, class Cost = std::int64_t, class Edges = virtual_map<Node, vector<typename internal::graph_impl::edge<Node, Cost>>>> struct virtual_graph : internal::graph_impl::mixin<internal::graph_impl::virtual_base<Node, Cost, Edges>> { private: using base = internal::graph_impl::mixin<internal::graph_impl::virtual_base<Node, Cost, Edges>>; public: using size_type = typename base::size_type; using edge = typename internal::graph_impl::edge<Node, Cost>; private: size_type _n = 0; public: template<class F> explicit virtual_graph(F&& f, const size_type n = 0) noexcept(NO_EXCEPT) : base(n, std::forward<F>(f)), _n(n) {} }; } // namespace uni #line 9 "graph/centroid_decomposition.hpp" namespace uni { // Thanks to: https://qiita.com/drken/items/4b4c3f1824339b090202 template<class Graph = graph<>> struct centroid_decomposition { using size_type = internal::size_t; std::vector<size_type> centroids; private: const Graph& graph; std::vector<size_type> _size, _parent; std::vector<bool> _used; public: centroid_decomposition(const Graph& _graph) noexcept(NO_EXCEPT) : graph(_graph), _size(graph.vertices()), _parent(graph.vertices()), _used(graph.vertices()) {} inline const auto& sizes() const noexcept(NO_EXCEPT) { return this->_size; } inline const auto& parents() const noexcept(NO_EXCEPT) { return this->_parent; } inline const auto& used() const noexcept(NO_EXCEPT) { return this->_used; } inline size_type size(const size_type v) const noexcept(NO_EXCEPT) { assert(0 <= v && v < this->graph.vertices()); return this->_size[v]; } inline size_type parent(const size_type v) const noexcept(NO_EXCEPT) { assert(0 <= v && v < this->graph.vertices()); return this->_parent[v]; } inline bool used(const size_type v) const noexcept(NO_EXCEPT) { assert(0 <= v && v < this->graph.vertices()); return this->_used[v]; } const std::vector<size_type>& find(const size_type v, const size_type sz, const size_type p = -1) noexcept(NO_EXCEPT) { assert(not this->_used[v]); this->_size[v] = 1, this->_parent[v] = p; bool found = true; ITR(e, this->graph[v]) { if(e.to == p) continue; if(this->_used[e.to]) continue; this->find(e.to, sz, v); if(this->_size[e.to] > sz / 2) found = false; this->_size[v] += this->_size[e.to]; } if(sz - this->_size[v] > sz / 2) found = false; if(found) this->centroids.push_back(v); return this->centroids; } auto decompose(const size_type root, const size_type sz) noexcept(NO_EXCEPT) { assert(not this->_used[root]); std::vector<std::pair<size_type,size_type>> subtrees; this->centroids.clear(); this->find(root, sz); const size_type centroid = this->centroids[0]; this->_used[centroid] = true; ITR(e, this->graph[centroid]) { if(this->_used[e.to]) continue; if(e.to == this->_parent[centroid]) { subtrees.emplace_back(e.to, sz - this->_size[centroid]); } else { subtrees.emplace_back(e.to, this->_size[e.to]); } } return std::make_pair(centroid, subtrees); } auto decompose(const size_type root = 0) noexcept(NO_EXCEPT) { return this->decompose(root, this->graph.vertices()); } }; } // namespace uni #line 2 "graph/centroid_path_decomposition.hpp" #line 7 "graph/centroid_path_decomposition.hpp" #line 9 "graph/centroid_path_decomposition.hpp" #line 12 "graph/centroid_path_decomposition.hpp" #line 14 "graph/centroid_path_decomposition.hpp" namespace uni { // Thanks to: https://kazuma8128.hatenablog.com/entry/2018/07/16/010500#fn-96e76557 class centroid_path_decomposition { using size_type = internal::size_t; private: std::vector<std::vector<size_type>> graph; public: std::vector<size_type> in, out, size, head, parent; private: size_type _cur = 0; void _erase_parent(const size_type v, const size_type p) noexcept(NO_EXCEPT) { this->parent[v] = p; ITRR(nv, graph[v]) { if(nv == this->graph[v].back()) break; if(nv == p) std::swap(nv, this->graph[v].back()); this->_erase_parent(nv, v); } this->graph[v].pop_back(); } void _race_size(const size_type v) noexcept(NO_EXCEPT) { ITRR(nv, this->graph[v]) { this->_race_size(nv); this->size[v] += this->size[nv]; if(this->size[nv] > this->size[this->graph[v].front()]) std::swap(nv, this->graph[v].front()); } } void _race_path(const size_type v) noexcept(NO_EXCEPT) { this->in[v] = this->_cur++; ITR(nv, this->graph[v]) { this->head[nv] = (nv == this->graph[v].front() ? this->head[v] : nv); this->_race_path(nv); } this->out[v] = this->_cur; } public: template<class Graph> centroid_path_decomposition(const Graph& _graph, const size_type root = 0) noexcept(NO_EXCEPT) : graph(_graph.size()), in(_graph.size(), -1), out(_graph.size(), -1), size(_graph.size(), 1), head(_graph.size()), parent(_graph.size(), -1) { REP(v, _graph.size()) ITR(nv, _graph[v]) { this->graph[v].push_back(nv); } this->build(root); } void build(const size_type root = 0) noexcept(NO_EXCEPT) { ITR(v, this->graph[root]) this->_erase_parent(v, root); this->_race_size(root); this->head[root] = root; this->_race_path(root); } size_type id(const size_type v) noexcept(NO_EXCEPT) { return this->in[v]; } size_type lca(size_type u, size_type v) const noexcept(NO_EXCEPT) { while(true) { if(this->in[u] > this->in[v]) std::swap(u, v); if(this->head[u] == this->head[v]) return u; v = this->parent[this->head[v]]; } } template<class F> void edges_on_path(size_type u, size_type v, F&& f) noexcept(NO_EXCEPT) { while(true) { if(this->in[u] > this->in[v]) std::swap(u, v); if(this->head[u] != this->head[v]) { f(this->in[this->head[v]] - 1, this->in[v]); v = this->parent[this->head[v]]; } else { if(u != v) f(this->in[u], this->in[v]); break; } } } template<class F> void nodes_on_path(size_type u, size_type v, F&& f) noexcept(NO_EXCEPT) { while (true) { if (this->in[u] > this->in[v]) std::swap(u, v); f(std::max(this->in[this->head[v]], this->in[u]), this->in[v]); if (this->head[u] != this->head[v]) v = this->parent[this->head[v]]; else { break; } } } template<class F> void subtree(const size_type v, F&& f) noexcept(NO_EXCEPT) { f(this->in[v], this->out[v]); } }; } // namespace uni #line 2 "graph/connected_components.hpp" #line 5 "graph/connected_components.hpp" #line 7 "graph/connected_components.hpp" #line 11 "graph/connected_components.hpp" template<class Graph> uni::disjoint_set uni::internal::graph_impl::mixin<Graph>::components() const noexcept(NO_EXCEPT) { uni::disjoint_set disjoint_set(this->vertices()); ITR(edges, *this) ITR(_id, u, v, _w, _idx, edges) { disjoint_set.merge(u, v); } return disjoint_set; } #line 2 "graph/is_bipartite.hpp" #line 6 "graph/is_bipartite.hpp" #line 8 "graph/is_bipartite.hpp" #line 11 "graph/is_bipartite.hpp" template<class Graph> bool uni::internal::graph_impl::mixin<Graph>::is_bipartite() const noexcept(NO_EXCEPT) { valarray<std::int8_t> color(0, this->vertices()); this->is_bipartite(&color); return true; } template<class Graph> template<class Colors> bool uni::internal::graph_impl::mixin<Graph>::is_bipartite(Colors *const color) const noexcept(NO_EXCEPT) { color->assign(this->vertices(), 0); REP(s, this->vertices()) { if(color->operator[](s) != 0) continue; std::stack<size_type> stack; stack.push(s); color->operator[](s) = 1; while(not stack.empty()) { auto v = stack.top(); stack.pop(); auto c = color->operator[](v); ITR(nv, this->operator[](v)) { if(color->operator[](nv) == c) return false; if(color->operator[](nv) == 0) { color->operator[](nv) = -c; stack.push(nv); } } } } return true; } #line 2 "graph/lowest_common_ancestor.hpp" #line 5 "graph/lowest_common_ancestor.hpp" #line 8 "graph/lowest_common_ancestor.hpp" #line 11 "graph/lowest_common_ancestor.hpp" #line 14 "graph/lowest_common_ancestor.hpp" #line 16 "graph/lowest_common_ancestor.hpp" namespace uni { template<class Graph> struct lowest_common_ancestor { using size_type = internal::size_t; using graph_type = Graph; using edge_type = typename graph_type::edge_type; using cost_type = typename graph_type::cost_type; valarray<valarray<size_type>> parent; valarray<size_type> depth; valarray<cost_type> cost; private: void dfs(const graph_type &G, const edge_type& e) noexcept(NO_EXCEPT) { this->parent[0][e.to] = e.from; if(e.from >= 0) { this->depth[e.to] = this->depth[e.from] + 1; this->cost[e.to] = this->cost[e.from] + e.cost; } ITR(f, G[e.to]) { if(f.to != e.from) dfs(G, f); } } public: lowest_common_ancestor(const graph_type &G, const size_type root = 0) noexcept(NO_EXCEPT) { this->init(G, root); } void init(const graph_type &G, const size_type root = 0) noexcept(NO_EXCEPT) { const size_type n = static_cast<size_type>(G.size()); const size_type d = std::bit_width<std::make_unsigned_t<size_type>>(n); this->parent.assign(d, valarray<size_type>(n, -1)); this->depth.assign(n, 0), this->cost.assign(n, 0); this->dfs(G, edge_type(-1, root, 0)); REP(k, d-1) REP(v, n) { if(this->parent[k][v] < 0) this->parent[k+1][v] = -1; else this->parent[k+1][v] = this->parent[k][this->parent[k][v]]; } } size_type operator()(const size_type u, const size_type v) const noexcept(NO_EXCEPT) { return this->find(u, v); } size_type find(size_type u, size_type v) const noexcept(NO_EXCEPT) { if(this->depth[u] < this->depth[v]) std::swap(u, v); size_type d = static_cast<size_type>(this->parent.size()); REP(k, d) { if((this->depth[u] - this->depth[v]) >> k & 1) u = this->parent[k][u]; } if(u == v) return u; REPD(k, d) { if(this->parent[k][u] != this->parent[k][v]) { u = this->parent[k][u]; v = this->parent[k][v]; } } return this->parent[0][u]; } size_type path_length(const size_type u, const size_type v) const noexcept(NO_EXCEPT) { return this->depth[u] + this->depth[v] - 2 * this->depth[find(u, v)]; } size_type distance(const size_type u, const size_type v) const noexcept(NO_EXCEPT) { return this->cost[u] + this->cost[v] - 2 * this->cost[find(u, v)]; } }; } // namespace uni #line 2 "graph/manhattan_minimum_spanning_tree.hpp" #line 9 "graph/manhattan_minimum_spanning_tree.hpp" #line 12 "graph/manhattan_minimum_spanning_tree.hpp" #line 15 "graph/manhattan_minimum_spanning_tree.hpp" #line 17 "graph/manhattan_minimum_spanning_tree.hpp" #line 19 "graph/manhattan_minimum_spanning_tree.hpp" #line 2 "graph/spanning_tree.hpp" #line 6 "graph/spanning_tree.hpp" #line 8 "graph/spanning_tree.hpp" namespace uni { namespace internal { namespace graph_impl { template<class G, template<class...> class Compare, class Cost, class Size> std::optional<Cost> kruskal(const G& graph, const Compare<std::tuple<Cost, Size, Size>> compare, G *const mst = nullptr) noexcept(NO_EXCEPT) { disjoint_set ds(graph.size()); std::vector<std::tuple<Cost, Size, Size>> edges; REP(u, graph.size()) ITR(e, graph[u]) { edges.emplace_back(e.cost, u, e.to); } std::ranges::sort(edges, compare); if(mst) mst->clear(), mst->resize(graph.size()); Cost res = 0; typename G::size_type cnt = 0; ITR(w, u, v, edges) { if(not ds.same(u, v)) { ds.merge(u, v); if(mst) mst->add_edge_bidirectionally(u, v, w); res += w; ++cnt; } } assert(cnt <= graph.size() - 1); if(cnt != graph.size() - 1) return {}; return res; } } // namespace graph_impl } // namespace internal } // namespace uni template<class Graph> inline auto uni::internal::graph_impl::mixin<Graph>::minimum_spanning_tree(internal::graph_impl::mixin<Graph> *const mst) const noexcept(NO_EXCEPT) { return uni::internal::graph_impl::kruskal< uni::internal::graph_impl::mixin<Graph>, std::less, cost_type, size_type >(*this, {}, mst); } template<class Graph> inline auto uni::internal::graph_impl::mixin<Graph>::maximum_spanning_tree(internal::graph_impl::mixin<Graph> *const mst) const noexcept(NO_EXCEPT) { return uni::internal::graph_impl::kruskal< uni::internal::graph_impl::mixin<Graph>, std::less, cost_type, size_type >(*this, {}, mst); } #line 22 "graph/manhattan_minimum_spanning_tree.hpp" namespace uni { // TODO: Vector View template < std::input_iterator I0, std::input_iterator I1, std::sentinel_for<I0> S0, std::sentinel_for<I1> S1 > auto manhattan_mst_candidate_edges( I0 x_first, S0 x_last, I1 y_first, S1 y_last ) noexcept(NO_EXCEPT) { using size_type = internal::size_t; using cost_type = std::common_type_t<std::iter_value_t<I0>, std::iter_value_t<I1>>; std::vector<cost_type> xs(x_first, x_last), ys(y_first, y_last); assert(xs.size() == ys.size()); std::vector<size_type> indices(xs.size()); std::iota(ALL(indices), 0); vector<std::tuple<size_type, size_type, cost_type>> res; REP(_0, 2) { REP(_1, 2) { std::ranges::sort(indices, [&](const auto i, const auto j) { return xs[i] + ys[i] < xs[j] + ys[j]; }); std::map<cost_type,size_type> scan; ITR(i, indices) { for(auto itr = scan.lower_bound(-ys[i]); itr!=scan.end(); itr=scan.erase(itr)) { const auto j = itr->second; if(xs[i] - xs[j] < ys[i] - ys[j]) break; res.emplace_back(i, j, std::abs(xs[i] - xs[j]) + std::abs(ys[i] - ys[j])); } scan[-ys[i]] = i; } std::swap(xs, ys); } ITRR(x, xs) x *= -1; } std::ranges::sort(res, [&](const auto& p, const auto& q) { return std::get<2>(p) < std::get<2>(q); }); return res; } template < std::input_iterator I0, std::input_iterator I1, std::sentinel_for<I0> S0, std::sentinel_for<I1> S1 > auto manhattan_mst_edges( I0 x_first, S0 x_last, I1 y_first, S1 y_last, std::common_type_t<std::iter_value_t<I0>, std::iter_value_t<I1>> *const cost_sum = nullptr ) noexcept(NO_EXCEPT) { using cost_type = std::common_type_t<std::iter_value_t<I0>, std::iter_value_t<I1>>; using size_type = internal::size_t; assert(std::ranges::distance(x_first, x_last) == std::ranges::distance(y_first, y_last)); if(cost_sum) *cost_sum = 0; vector<std::tuple<size_type, size_type, cost_type>> res; disjoint_set uf(std::ranges::distance(x_first, x_last)); ITR(u, v, w, (manhattan_mst_candidate_edges<I0,I1>(x_first, x_last, y_first, y_last))) { if(not uf.same(u, v)) { uf.merge(u, v); res.emplace_back(u, v, w); if(cost_sum) *cost_sum += w; } } return res; } template<class Graph> template< std::input_iterator I0, std::input_iterator I1, std::sentinel_for<I0> S0, std::sentinel_for<I1> S1 > typename Graph::cost_type internal::graph_impl::mixin<Graph>::build_manhattan_mst( I0 x_first, S0 x_last, I1 y_first, S1 y_last ) noexcept(NO_EXCEPT) { assert(std::ranges::distance(x_first, x_last) == std::ranges::distance(y_first, y_last)); cost_type res = 0; const auto edges = manhattan_mst_edges<I0, I1, S0, S1>(x_first, x_last, y_first, y_last); ITR(u, v, w, edges) { this->add_edge_bidirectionally(u, v, w); } return res; } } // namespace uni #line 2 "graph/maximum_bipartite_matching.hpp" #include <atcoder/maxflow> #line 9 "graph/maximum_bipartite_matching.hpp" #line 12 "graph/maximum_bipartite_matching.hpp" #line 14 "graph/maximum_bipartite_matching.hpp" namespace uni { struct maximum_bipartite_matching { // using size_type = internal::size_t; using size_type = int; protected: using MF = atcoder::mf_graph<size_type>; size_type _m, _n, _s, _edges = 0; MF _mf; public: explicit maximum_bipartite_matching(const size_type n) noexcept(NO_EXCEPT) : maximum_bipartite_matching(n, n) {} maximum_bipartite_matching(const size_type m, const size_type n) noexcept(NO_EXCEPT) : _m(m), _n(n), _s(m + n), _mf(m + n + 2) { REP(i, m) { this->_mf.add_edge(this->_s, i, 1); } REP(i, n) { this->_mf.add_edge(m + i, this->_s + 1, 1); } } inline auto& add(const size_type i, const size_type j) noexcept(NO_EXCEPT) { assert(0 <= i && i < this->_m); assert(0 <= j && j < this->_n); this->_mf.add_edge(i, this->_m + j, 1); ++this->_edges; return *this; } inline size_type max_matched() noexcept(NO_EXCEPT) { return this->_mf.flow(this->_s, this->_s + 1); } inline auto get_matching() noexcept(NO_EXCEPT) { this->max_matched(); vector<spair<size_type>> res; REP(i, this->_edges) { const auto edge = this->_mf.get_edge(this->_s + i); if(edge.flow == 0) continue; res.emplace_back(edge.from, edge.to - this->_m); } return res; } }; } // namespace uni #line 2 "graph/minimum_paph_cover.hpp" #line 5 "graph/minimum_paph_cover.hpp" #line 8 "graph/minimum_paph_cover.hpp" #line 11 "graph/minimum_paph_cover.hpp" template<class Graph> typename uni::internal::graph_impl::mixin<Graph>::size_type uni::internal::graph_impl::mixin<Graph>::minimum_paph_cover_size_as_dag() const noexcept(NO_EXCEPT) { uni::maximum_bipartite_matching bm(this->size()); REP(i, this->size()) ITR(j, (*this)[i]) { bm.add(i, j.to); } return this->size() - bm.max_matched(); } #line 2 "graph/parse_grid.hpp" #line 4 "graph/parse_grid.hpp" #line 7 "graph/parse_grid.hpp" template<class Graph> template<bool REV, class G, class U> void uni::internal::graph_impl::mixin<Graph>::parse_grid(const G &grid, U available) noexcept(NO_EXCEPT) { this->clear(); this->resize(grid.height() * grid.width()); REP(i, grid.height()) REP(j, grid.width()) { if(REV ^ (grid(i, j) != available)) continue; if(i+1 < grid.height() and (REV ^ (grid(i+1, j) == available))) { this->template add_edge_bidirectionally(grid.id(i, j), grid.id(i+1, j)); } if(j+1 < grid.width() and (REV ^ (grid(i, j+1) == available))) { this->template add_edge_bidirectionally(grid.id(i, j), grid.id(i, j+1)); } } } #line 2 "graph/reachability_test.hpp" #line 6 "graph/reachability_test.hpp" #line 10 "graph/reachability_test.hpp" #line 12 "graph/reachability_test.hpp" #line 2 "graph/topological_sort.hpp" #line 6 "graph/topological_sort.hpp" #line 10 "graph/topological_sort.hpp" template<class Graph> template<class comparer> bool uni::internal::graph_impl::mixin<Graph>::sort_topologically_with_priority(uni::vector<node_type> *const sorted) const noexcept(NO_EXCEPT) { sorted->clear(); std::vector<size_type> in_degs(this->size()); ITR(v, *this) ITR(e, v) ++in_degs[e.to]; std::priority_queue<node_type,std::vector<node_type>,comparer> que; REP(i, this->size()) if(in_degs[i] == 0) que.push(i); while(not que.empty()) { const node_type v = que.top(); que.pop(); ITR(u, (*this)[v]) if(!(--in_degs[u.to])) que.push(u.to); sorted->push_back(v); } return std::ranges::ssize(*sorted) == std::ranges::ssize(*this); } template<class Graph> template<class comparer> bool uni::internal::graph_impl::mixin<Graph>::sort_topologically_with_priority() const noexcept(NO_EXCEPT) { uni::vector<node_type> vs; return this->sort_topologically_with_priority<comparer>(&vs); } template<class Graph> bool uni::internal::graph_impl::mixin<Graph>::sort_topologically(uni::vector<node_type> *const sorted) const noexcept(NO_EXCEPT) { sorted->clear(); std::vector<size_type> in_degs(this->size()); ITR(v, *this) ITR(e, v) ++in_degs[e.to]; std::queue<node_type> que; REP(i, this->size()) if(in_degs[i] == 0) que.push(i); while(not que.empty()) { const node_type v = que.front(); que.pop(); ITR(u, (*this)[v]) if(!(--in_degs[u.to])) que.push(u.to); sorted->push_back(v); } return std::ranges::ssize(*sorted) == std::ranges::ssize(*this); } template<class Graph> bool uni::internal::graph_impl::mixin<Graph>::sort_topologically() const noexcept(NO_EXCEPT) { std::vector<node_type> vs; return this->sort_topologically(&vs); } #line 15 "graph/reachability_test.hpp" #line 2 "view/chunk.hpp" #line 6 "view/chunk.hpp" #line 9 "view/chunk.hpp" #line 11 "view/chunk.hpp" namespace uni { template<std::ranges::view View> requires std::ranges::input_range<View> struct chunk_view : std::ranges::view_interface<chunk_view<View>> { private: View _base; std::ranges::range_difference_t<View> _n; std::ranges::range_difference_t<View> _remainder = 0; std::optional<std::ranges::iterator_t<View>> _current; struct outer_iterator; struct inner_iterator; public: constexpr explicit chunk_view(View base, std::ranges::range_difference_t<View> n) : _base(std::move(base)), _n(n) { assert(n >= 0); } constexpr View base() const & requires std::copy_constructible<View> { return this->_base; } constexpr View base() && { return std::move(this->_base); } constexpr outer_iterator begin() { this->_current = std::ranges::begin(this->_base); this->_remainder = this->_n; return outer_iterator(*this); } constexpr std::default_sentinel_t end() const noexcept { return std::default_sentinel; } constexpr auto size() requires std::ranges::sized_range<View> { return to_unsigned(div_ceil(std::ranges::distance(this->_base), this->_n)); } constexpr auto size() const requires std::ranges::sized_range<const View> { return to_unsigned(div_ceil(std::ranges::distance(this->_base), this->_n)); } }; template<class Range> chunk_view(Range&&, std::ranges::range_difference_t<Range>) -> chunk_view<std::views::all_t<Range>>; template<std::ranges::view View> requires std::ranges::input_range<View> struct chunk_view<View>::outer_iterator { private: chunk_view *_parent; constexpr explicit outer_iterator(chunk_view &parent) noexcept : _parent(std::addressof(parent)) {} friend chunk_view; public: using iterator_concept = std::input_iterator_tag; using difference_type = std::ranges::range_difference_t<View>; struct value_type; outer_iterator(outer_iterator &&) = default; outer_iterator &operator=(outer_iterator &&) = default; constexpr value_type operator*() const { assert(*this != std::default_sentinel); return value_type(*this->_parent); } constexpr outer_iterator &operator++() { assert(*this != std::default_sentinel); std::ranges::advance(*this->_parent->_current, this->_parent->_remainder, std::ranges::end(this->_parent->_base)); this->_parent->_remainder = this->_parent->_n; return *this; } constexpr void operator++(int) { ++*this; } friend constexpr bool operator==(const outer_iterator &lhs, std::default_sentinel_t) { return *lhs._parent->_current == std::ranges::end(lhs._parent->_base) && lhs._parent->_remainder != 0; } friend constexpr difference_type operator-(std::default_sentinel_t, const outer_iterator &rhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { const auto dist = std::ranges::end(rhs._parent->_base) - *rhs._parent->_current; if(dist < rhs._parent->_remainder) return dist == 0 ? 0 : 1; return 1 + div_ceil(dist - rhs._parent->_remainder, rhs._parent->_n); } friend constexpr difference_type operator-(const outer_iterator &lhs, std::default_sentinel_t rhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { return -(rhs - lhs); } }; template<std::ranges::view View> requires std::ranges::input_range<View> struct chunk_view<View>::outer_iterator::value_type : std::ranges::view_interface<value_type> { private: chunk_view *_parent; constexpr explicit value_type(chunk_view &parent) noexcept : _parent(std::addressof(parent)) {} friend outer_iterator; public: constexpr inner_iterator begin() const noexcept { return inner_iterator(*this->_parent); } constexpr std::default_sentinel_t end() const noexcept { return std::default_sentinel; } constexpr auto size() const requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { return to_unsigned(std::ranges::min(this->_parent->_remainder, std::ranges::end(this->_parent->_base) - *this->_parent->_current)); } }; template<std::ranges::view View> requires std::ranges::input_range<View> struct chunk_view<View>::inner_iterator { private: chunk_view *_parent; constexpr explicit inner_iterator(chunk_view &parent) noexcept : _parent(std::addressof(parent)) {} friend outer_iterator::value_type; public: using iterator_concept = std::input_iterator_tag; using difference_type = std::ranges::range_difference_t<View>; using value_type = std::ranges::range_value_t<View>; inner_iterator(inner_iterator &&) = default; inner_iterator &operator=(inner_iterator &&) = default; constexpr const std::ranges::iterator_t<View> &base() const & { return *this->_parent->_current; } constexpr std::ranges::range_reference_t<View> operator*() const { assert(*this != std::default_sentinel); return **this->_parent->_current; } constexpr inner_iterator &operator++() { assert(*this != std::default_sentinel); ++*this->_parent->_current; if(*this->_parent->_current == std::ranges::end(this->_parent->_base)) { this->_parent->_remainder = 0; } else { --this->_parent->_remainder; } return *this; } constexpr void operator++(int) { ++*this; } friend constexpr bool operator==(const inner_iterator &lhs, std::default_sentinel_t) noexcept { return lhs._parent->_remainder == 0; } friend constexpr difference_type operator-(std::default_sentinel_t, const inner_iterator &rhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { return std::ranges::min(rhs._parent->_remainder, std::ranges::end(rhs._parent->_base) - *rhs._parent->_current); } friend constexpr difference_type operator-(const inner_iterator &lhs, std::default_sentinel_t rhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { return -(rhs - lhs); } }; template<std::ranges::view View> requires std::ranges::forward_range<View> struct chunk_view<View> : std::ranges::view_interface<chunk_view<View>> { private: View _base; std::ranges::range_difference_t<View> _n; template<bool> struct iterator; public: constexpr explicit chunk_view(View base, const std::ranges::range_difference_t<View> n) : _base(std::move(base)), _n(n) { assert(n > 0); } constexpr View base() const & requires std::copy_constructible<View> { return this->_base; } constexpr View base() && { return std::move(this->_base); } constexpr auto begin() requires(!internal::simple_view<View>) { return iterator<false>(this, std::ranges::begin(this->_base)); } constexpr auto begin() const requires std::ranges::forward_range<const View> { return iterator<true>(this, std::ranges::begin(this->_base)); } constexpr auto end() requires(!internal::simple_view<View>) { if constexpr(std::ranges::common_range<View> && std::ranges::sized_range<View>) { const auto missing = (this->_n - std::ranges::distance(this->_base) % this->_n) % this->_n; return iterator<false>(this, std::ranges::end(this->_base), missing); } else if constexpr(std::ranges::common_range<View> && !std::ranges::bidirectional_range<View>) { return iterator<false>(this, std::ranges::end(this->_base)); } else { return std::default_sentinel; } } constexpr auto end() const requires std::ranges::forward_range<const View> { if constexpr(std::ranges::common_range<const View> && std::ranges::sized_range<const View>) { auto missing = (this->_n - std::ranges::distance(this->_base) % this->_n) % this->_n; return iterator<true>(this, std::ranges::end(this->_base), missing); } else if constexpr(std::ranges::common_range<const View> && !std::ranges::bidirectional_range<const View>) { return iterator<true>(this, std::ranges::end(this->_base)); } else { return std::default_sentinel; } } constexpr auto size() requires std::ranges::sized_range<View> { return to_unsigned(div_ceil(std::ranges::distance(this->_base), this->_n)); } constexpr auto size() const requires std::ranges::sized_range<const View> { return to_unsigned(div_ceil(std::ranges::distance(this->_base), this->_n)); } }; template<std::ranges::view View> requires std::ranges::forward_range<View> template<bool CONST> struct chunk_view<View>::iterator { private: using Parent = internal::maybe_const_t<CONST, chunk_view>; using Base = internal::maybe_const_t<CONST, View>; std::ranges::iterator_t<Base> _current = std::ranges::iterator_t<Base>(); std::ranges::sentinel_t<Base> _end = std::ranges::sentinel_t<Base>(); std::ranges::range_difference_t<Base> _n = 0; std::ranges::range_difference_t<Base> _missing = 0; constexpr iterator(Parent *parent, std::ranges::iterator_t<Base> current, const std::ranges::range_difference_t<Base> missing = 0) : _current(current), _end(std::ranges::end(parent->_base)), _n(parent->_n), _missing(missing) {} friend chunk_view; public: using iterator_category = std::input_iterator_tag; using iterator_concept = internal::most_primitive_iterator_concept<false, Base>; using value_type = decltype(std::views::take(std::ranges::subrange(_current, _end), _n)); using difference_type = std::ranges::range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!CONST> itr) requires CONST && std::convertible_to<std::ranges::iterator_t<View>, std::ranges::iterator_t<Base>> && std::convertible_to<std::ranges::sentinel_t<View>, std::ranges::sentinel_t<Base>> : _current(std::move(itr._current)), _end(std::move(itr._end)), _n(itr._n), _missing(itr._missing) {} constexpr std::ranges::iterator_t<Base> base() const { return this->_current; } constexpr value_type operator*() const { assert(this->_current != this->_end); return std::views::take(std::ranges::subrange(this->_current, this->_end), this->_n); } constexpr iterator &operator++() { assert(this->_current != this->_end); this->_missing = std::ranges::advance(this->_current, this->_n, this->_end); return *this; } constexpr iterator operator++(int) { auto temp = *this; return ++*this, temp; } constexpr iterator &operator--() requires std::ranges::bidirectional_range<Base> { std::ranges::advance(this->_current, this->_missing - this->_n); this->_missing = 0; return *this; } constexpr iterator operator--(int) requires std::ranges::bidirectional_range<Base> { auto temp = *this; return --*this, temp; } constexpr iterator &operator+=(difference_type lhs) requires std::ranges::random_access_range<Base> { if(lhs > 0) { assert(std::ranges::distance(this->_current, this->_end) > this->_n * (lhs - 1)); this->_missing = std::ranges::advance(this->_current, this->_n * lhs, this->_end); } else if(lhs < 0) { std::ranges::advance(this->_current, this->_n * lhs + this->_missing); this->_missing = 0; } return *this; } constexpr iterator &operator-=(difference_type lhs) requires std::ranges::random_access_range<Base> { return *this += -lhs; } constexpr value_type operator[](difference_type n) const requires std::ranges::random_access_range<Base> { return *(*this + n); } friend constexpr bool operator==(const iterator &lhs, const iterator &rhs) { return lhs._current == rhs._current; } friend constexpr bool operator==(const iterator &lhs, std::default_sentinel_t) { return lhs._current == lhs._end; } friend constexpr bool operator<(const iterator &lhs, const iterator &rhs) requires std::ranges::random_access_range<Base> { return lhs._current > rhs._current; } friend constexpr bool operator>(const iterator &lhs, const iterator &rhs) requires std::ranges::random_access_range<Base> { return rhs < lhs; } friend constexpr bool operator<=(const iterator &lhs, const iterator &rhs) requires std::ranges::random_access_range<Base> { return !(rhs < lhs); } friend constexpr bool operator>=(const iterator &lhs, const iterator &rhs) requires std::ranges::random_access_range<Base> { return !(lhs < rhs); } friend constexpr auto operator<=>(const iterator &lhs, const iterator &rhs) requires std::ranges::random_access_range<Base> && std::three_way_comparable<std::ranges::iterator_t<Base>> { return lhs._current <=> rhs._current; } friend constexpr iterator operator+(const iterator &itr, const difference_type count) requires std::ranges::random_access_range<Base> { auto res = itr; return res += count, res; } friend constexpr iterator operator+(const difference_type count, const iterator &itr) requires std::ranges::random_access_range<Base> { auto res = itr; return res += count, res; } friend constexpr iterator operator-(const iterator &itr, const difference_type count) requires std::ranges::random_access_range<Base> { auto res = itr; return res -= count, res; } friend constexpr difference_type operator-(const iterator &lhs, const iterator &rhs) requires std::sized_sentinel_for<std::ranges::iterator_t<Base>, std::ranges::iterator_t<Base>> { return (lhs._current - rhs._current + lhs._missing - rhs._missing) / lhs._n; } friend constexpr difference_type operator-(std::default_sentinel_t rhs, const iterator &lhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<Base>, std::ranges::iterator_t<Base>> { return div_ceil(lhs._end - lhs._current, lhs._n); } friend constexpr difference_type operator-(const iterator &lhs, std::default_sentinel_t rhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<Base>, std::ranges::iterator_t<Base>> { return -(rhs - lhs); } }; namespace views { namespace internal { template<class Range, typename Diff> concept can_chunk_view = requires { chunk_view(std::declval<Range>(), std::declval<Diff>()); }; } // namespace internal struct Chunk : adaptor::range_adaptor<Chunk> { template<std::ranges::viewable_range Range, class Diff = std::ranges::range_difference_t<Range>> requires internal::can_chunk_view<Range, Diff> constexpr auto operator() [[nodiscard]] (Range &&res, std::type_identity_t<Diff> n) const { return chunk_view(std::forward<Range>(res), n); } using adaptor::range_adaptor<Chunk>::operator(); static constexpr int arity = 2; static constexpr bool has_simple_extra_args = true; }; inline constexpr Chunk chunk; } // namespace views } // namespace uni namespace std::ranges { template<class View> inline constexpr bool enable_borrowed_range<uni::chunk_view<View>> = forward_range<View> && enable_borrowed_range<View>; } // namespace std::ranges #line 2 "view/enumerate.hpp" #line 6 "view/enumerate.hpp" #line 10 "view/enumerate.hpp" namespace uni { namespace internal { template<class Range> concept range_with_movable_reference = std::ranges::input_range<Range> && std::move_constructible<std::ranges::range_reference_t<Range>> && std::move_constructible<std::ranges::range_rvalue_reference_t<Range>>; } // namespace internal template<std::ranges::view View> requires internal::range_with_movable_reference<View> struct enumerate_view : public std::ranges::view_interface<enumerate_view<View>> { private: View _base = View(); template<bool Const> class iterator; template<bool Const> class sentinel; public: enumerate_view() requires std::default_initializable<View> = default; constexpr explicit enumerate_view(View base) : _base(std::move(base)) {} constexpr auto begin() requires(!internal::simple_view<View>) { return iterator<false>(std::ranges::begin(this->_base), 0); } constexpr auto begin() const requires internal::range_with_movable_reference<const View> { return iterator<true>(std::ranges::begin(this->_base), 0); } constexpr auto end() requires(!internal::simple_view<View>) { if constexpr(std::ranges::common_range<View> && std::ranges::sized_range<View>) { return iterator<false>(std::ranges::end(_base), std::ranges::distance(this->_base)); } else { return sentinel<false>(std::ranges::end(_base)); } } constexpr auto end() const requires internal::range_with_movable_reference<const View> { if constexpr(std::ranges::common_range<const View> && std::ranges::sized_range<const View>) { return iterator<true>(std::ranges::end(_base), std::ranges::distance(_base)); } else { return sentinel<true>(std::ranges::end(_base)); } } constexpr auto size() requires std::ranges::sized_range<View> { return std::ranges::size(_base); } constexpr auto size() const requires std::ranges::sized_range<const View> { return std::ranges::size(_base); } constexpr View base() const & requires std::copy_constructible<View> { return _base; } constexpr View base() && { return std::move(_base); } }; template<class Range> enumerate_view(Range&& ) -> enumerate_view<std::views::all_t<Range>>; template<std::ranges::view View> requires internal::range_with_movable_reference<View> template<bool Const> class enumerate_view<View>::iterator { using Base = internal::maybe_const_t<Const, View>; friend enumerate_view; public: using iterator_category = std::iterator_traits<std::ranges::iterator_t<Base>>::iterator_category; using iterator_concept = internal::most_primitive_iterator_concept<Const, View>; using difference_type = std::ranges::range_difference_t<Base>; using value_type = std::tuple<difference_type, std::ranges::range_value_t<Base>>; private: using rangeeference_type = std::tuple<difference_type, std::ranges::range_reference_t<Base>>; std::ranges::iterator_t<Base> _current = std::ranges::iterator_t<Base>(); difference_type _pos = 0; constexpr explicit iterator(std::ranges::iterator_t<Base> current, const difference_type pos) : _current(std::move(current)), _pos(pos) {} public: iterator() requires std::default_initializable<std::ranges::iterator_t<Base>> = default; constexpr iterator(iterator<!Const> itr) requires Const && std::convertible_to<std::ranges::iterator_t<View>, std::ranges::iterator_t<Base>> : _current(std::move(itr._current)), _pos(itr._pos) {} constexpr const std::ranges::iterator_t<Base>& base() const & noexcept { return this->_current; } constexpr std::ranges::iterator_t<Base> base() && { return std::move(this->_current); } constexpr difference_type index() const noexcept { return this->_pos; } constexpr auto operator*() const { return rangeeference_type(this->_pos, *this->_current); } constexpr iterator& operator++() { ++this->_current; ++this->_pos; return *this; } constexpr void operator++(int) { ++*this; } constexpr iterator operator++(int) requires std::ranges::forward_range<Base> { auto temp = *this; ++*this; return temp; } constexpr iterator& operator--() requires std::ranges::bidirectional_range<Base> { --this->_current; --this->_pos; return *this; } constexpr iterator operator--(int) requires std::ranges::bidirectional_range<Base> { auto temp = *this; --*this; return temp; } constexpr iterator& operator+=(const difference_type diff) requires std::ranges::random_access_range<Base> { this->_current += diff; this->_pos += diff; return *this; } constexpr iterator& operator-=(const difference_type diff) requires std::ranges::random_access_range<Base> { this->_current -= diff; this->_pos -= diff; return *this; } constexpr auto operator[](const difference_type diff) const requires std::ranges::random_access_range<Base> { return rangeeference_type(this->_pos + diff, this->_current[diff]); } friend constexpr bool operator==(const iterator& lhs, const iterator& rhs) noexcept { return lhs._pos == rhs._pos; } friend constexpr std::strong_ordering operator<=>(const iterator& lhs, const iterator& rhs) noexcept { return lhs._pos <=> rhs._pos; } friend constexpr iterator operator+(iterator lhs, const difference_type rhs) requires std::ranges::random_access_range<Base> { return (lhs += rhs); } friend constexpr iterator operator+(const difference_type lhs, const iterator& rhs) requires std::ranges::random_access_range<Base> { return rhs += lhs; } friend constexpr iterator operator-(iterator& lhs, const difference_type rhs) requires std::ranges::random_access_range<Base> { return lhs -= rhs; } friend constexpr difference_type operator-(const iterator& lhs, const iterator& rhs) { return lhs._pos - rhs._pos; } friend constexpr auto iter_move(const iterator& itr) noexcept( noexcept (std::ranges::iter_move(itr._current)) && std::is_nothrow_move_constructible_v<std::ranges::range_rvalue_reference_t<Base>> ) { return std::tuple<difference_type, std::ranges::range_rvalue_reference_t<Base>>( itr._pos, std::ranges::iter_move(itr._current) ); } }; template<std::ranges::view View> requires internal::range_with_movable_reference<View> template<bool Const> class enumerate_view<View>::sentinel { using Base = internal::maybe_const_t<Const, View>; std::ranges::sentinel_t<Base> _end = std::ranges::sentinel_t<Base>(); constexpr explicit sentinel(std::ranges::sentinel_t<Base> end) : _end(std::move(end)) {} friend enumerate_view; public: sentinel() = default; constexpr sentinel(sentinel<!Const> other) requires Const && std::convertible_to<std::ranges::sentinel_t<View>, std::ranges::sentinel_t<Base>> : _end(std::move(other._end)) {} constexpr std::ranges::sentinel_t<Base> base() const { return this->_end; } template<bool Const_> requires std::sentinel_for< std::ranges::sentinel_t<Base>, std::ranges::iterator_t<internal::maybe_const_t<Const_, View>> > friend constexpr bool operator==(const iterator<Const_>& lhs, const sentinel& rhs) { return lhs._current == rhs._end; } template<bool Const_> requires std::sized_sentinel_for< std::ranges::sentinel_t<Base>, std::ranges::iterator_t<internal::maybe_const_t<Const_, View>> > friend constexpr std::ranges::range_difference_t<internal::maybe_const_t<Const_, View>> operator-(const iterator<Const_>& lhs, const sentinel& rhs) { return lhs._current - rhs._end; } template<bool Const_> requires std::sized_sentinel_for< std::ranges::sentinel_t<Base>, std::ranges::iterator_t<internal::maybe_const_t<Const_, View>>> friend constexpr std::ranges::range_difference_t<internal::maybe_const_t<Const_, View>> operator-(const sentinel& lhs, const iterator<Const_>& rhs) { return lhs._end - rhs._current; } }; namespace views { namespace internal { template<class T> concept can_enumerate_view = requires { enumerate_view<std::views::all_t<T>>(std::declval<T>()); }; } // namespace internal struct Enumerate : adaptor::range_adaptor_closure<Enumerate> { template<std::ranges::viewable_range Range> requires internal::can_enumerate_view<Range> constexpr auto operator() [[nodiscard]] (Range&& range) const { return enumerate_view<std::views::all_t<Range>>(std::forward<Range>(range)); } }; inline constexpr Enumerate enumerate; } // namespace views } // namespace uni namespace std::ranges { template<class T> inline constexpr bool enable_borrowed_range<uni::enumerate_view<T>> = enable_borrowed_range<T>; } // namespace std #line 18 "graph/reachability_test.hpp" namespace uni { template<class Graph> template<std::ranges::sized_range R> auto uni::internal::graph_impl::mixin<Graph>::test_reachability(R&& queries) const noexcept(NO_EXCEPT) { using impl_type = u128; constexpr auto CHUNK_SIZE = std::numeric_limits<impl_type>::digits; std::vector<bool> res(std::ranges::size(queries)); uni::vector<node_type> vs; this->sort_topologically(&vs); debug(queries); ITR(i, qs, queries | uni::views::chunk(CHUNK_SIZE) | uni::views::enumerate) { debug(qs); std::vector<impl_type> bits(this->size()); ITR(j, p, qs | uni::views::enumerate) { bits[p.first] = uni::set_bit(bits[p.first], j); } ITR(v, vs) ITR(nv, this->operator[](v)) { bits[nv] |= bits[v]; } ITR(j, p, qs | uni::views::enumerate) { res[i * CHUNK_SIZE + j] = uni::bit(bits[p.second], j); } } return res; } } // namespace uni #line 2 "graph/shortest_path.hpp" #line 5 "graph/shortest_path.hpp" #line 2 "graph/internal/bfs.hpp" #line 6 "graph/internal/bfs.hpp" #line 9 "graph/internal/bfs.hpp" #line 11 "graph/internal/bfs.hpp" #line 14 "graph/internal/bfs.hpp" #line 17 "graph/internal/bfs.hpp" template<class Graph> template<uni::internal::item_or_convertible_range<typename Graph::node_type> Source, class Dist, class Prev> void uni::internal::graph_impl::mixin<Graph>::shortest_path_without_cost( Source&& s, Dist *const dist, Prev *const prev, const node_type& unreachable, const node_type& root ) const noexcept(NO_EXCEPT) { dist->assign(this->size(), uni::numeric_limits<cost_type>::arithmetic_infinity()); if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->assign(this->size(), unreachable); std::queue<node_type> que; if constexpr(std::ranges::range<Source>) { ITR(v, s) { que.push(v), dist->operator[](v) = 0; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](v) = root; } } else { que.push(s), dist->operator[](s) = 0; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](s) = root; } while(!que.empty()) { const node_type v = que.front(); que.pop(); ITR(nv, this->operator[](v)) { if(dist->operator[](nv.to) < uni::numeric_limits<cost_type>::arithmetic_infinity()) { continue; } dist->operator[](nv.to) = dist->operator[](v) + 1; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](nv.to) = v; que.push(nv.to); } } } template<class Graph> template<uni::internal::item_or_convertible_range<typename Graph::node_type> Source> auto uni::internal::graph_impl::mixin<Graph>::shortest_path_without_cost(Source&& s) const noexcept(NO_EXCEPT) { uni::auto_holder<node_type, cost_type> dist; this->shortest_path_without_cost(std::forward<Source>(s), &dist); return dist; } #line 2 "graph/internal/01bfs.hpp" #line 7 "graph/internal/01bfs.hpp" #line 9 "graph/internal/01bfs.hpp" #line 12 "graph/internal/01bfs.hpp" #line 15 "graph/internal/01bfs.hpp" #line 18 "graph/internal/01bfs.hpp" template<class Graph> template<uni::internal::item_or_convertible_range<typename Graph::node_type> Source, class Dist, class Prev> void uni::internal::graph_impl::mixin<Graph>::shortest_path_with_01cost( Source&& s, Dist *const dist, Prev *const prev, const node_type& unreachable, const node_type& root ) const noexcept(NO_EXCEPT) { std::deque<node_type> que; dist->assign(this->size(), uni::numeric_limits<cost_type>::arithmetic_infinity()); if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->assign(this->size(), unreachable); if constexpr(std::ranges::range<Source>) { ITR(v, s) { que.push_back(v), dist->operator[](v) = 0; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](v) = root; } } else { que.push_back(s), dist->operator[](s) = 0; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](s) = root; } while(!que.empty()) { const auto u = que.front(); que.pop_front(); const cost_type d = dist->operator[](u); ITR(e, (*this)[u]) { const node_type v = e.to; const auto cost = e.cost; if(dist->operator[](v) <= d + cost) continue; dist->operator[](v) = d + cost; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](v) = u; if(cost) que.push_back(v); else que.push_front(v); } } } template<class Graph> template<uni::internal::item_or_convertible_range<typename Graph::node_type> Source> auto uni::internal::graph_impl::mixin<Graph>::shortest_path_with_01cost(Source&& s) const noexcept(NO_EXCEPT) { uni::auto_holder<typename uni::internal::graph_impl::mixin<Graph>::node_type, cost_type> dist; this->shortest_path_with_01cost(std::forward<Source>(s), &dist); return dist; } #line 2 "graph/internal/dijkstra.hpp" #line 7 "graph/internal/dijkstra.hpp" #line 9 "graph/internal/dijkstra.hpp" #line 11 "graph/internal/dijkstra.hpp" #line 13 "graph/internal/dijkstra.hpp" #line 16 "graph/internal/dijkstra.hpp" template<class Graph> template<uni::internal::item_or_convertible_range<typename Graph::node_type> Source, class Dist, class Prev> void uni::internal::graph_impl::mixin<Graph>::shortest_path_with_cost( Source&& s, Dist *const dist, Prev *const prev, const node_type& unreachable, const node_type& root ) const noexcept(NO_EXCEPT) { using state = std::pair<cost_type, node_type>; std::priority_queue<state, std::vector<state>, std::greater<state>> que; dist->assign(this->size(), uni::numeric_limits<cost_type>::arithmetic_infinity()); if constexpr(!std::same_as<Prev, std::nullptr_t>) prev->assign(this->size(), unreachable); if constexpr(std::ranges::range<Source>) { ITR(v, s) { que.emplace(0, v), dist->operator[](v) = 0; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](v) = root; } } else { que.emplace(0, s), dist->operator[](s) = 0; if constexpr(!std::is_same_v<Prev, std::nullptr_t>) prev->operator[](s) = root; } while(!que.empty()) { const auto [d, u] = que.top(); que.pop(); if(dist->operator[](u) < d) continue; ITR(e, this->operator[](u)) { const node_type v = e.to; const auto next = d + e.cost; if(dist->operator[](v) <= next) continue; dist->operator[](v) = next; if constexpr(!std::same_as<Prev, std::nullptr_t>) prev->operator[](v) = u; que.emplace(dist->operator[](v), v); } } } template<class Graph> template<uni::internal::item_or_convertible_range<typename Graph::node_type> Source> auto uni::internal::graph_impl::mixin<Graph>::shortest_path_with_cost(Source&& s) const noexcept(NO_EXCEPT) { uni::auto_holder<node_type, cost_type> dist; this->shortest_path_with_cost(std::forward<Source>(s), &dist); return dist; } #line 10 "graph/shortest_path.hpp" #line 12 "graph/shortest_path.hpp" namespace uni { template<class Node, class Prev, class Res> void restore_path(Node back, const Prev& prev, Res *const res) { res->clear(); while(back >= 0) { res->emplace_back(back); back = prev[back]; } std::ranges::reverse(*res); } template<class Node, class Prev, class Res = uni::vector<Node>> uni::vector<Node> restore_path(Node back, const Prev& prev) { uni::vector<Node> res; restore_path(back, prev, &res); return res; } } #line 2 "graph/tree_diamiter.hpp" #line 6 "graph/tree_diamiter.hpp" #line 8 "graph/tree_diamiter.hpp" namespace uni { namespace internal { template<class Graph> std::pair<typename Graph::cost_type, typename Graph::node_type> farthest(const Graph& tree, const typename Graph::node_type v, const typename Graph::node_type p, std::vector<typename Graph::node_type> *const prev = nullptr) { std::pair<typename Graph::cost_type, typename Graph::node_type> res = { 0, v }; for(auto nv : tree[v]) { if(nv.to == p) continue; auto next = farthest(tree, nv.to, v, prev); next.first += nv.cost; if(res.first < next.first) { if(prev) prev->operator[](nv.to) = v; res = next; } } return res; } } // namespace internal template<class Graph> auto tree_diamiter(const Graph& tree, std::vector<typename Graph::node_type> *const prev = nullptr) { const auto p = farthest(tree, 0, -1); return farthest(tree, p.second, -1, prev); } } // namespace uni #line 2 "graph/tree_hash.hpp" #line 6 "graph/tree_hash.hpp" #line 9 "graph/tree_hash.hpp" namespace uni { template<class Graph> auto tree_centers(const Graph& tree) { std::vector<typename Graph::node_type> prev(std::ranges::size(tree), -1); auto [ diam, v ] = tree_diamiter(tree, &prev); std::vector<typename Graph::node_type> res; { for(typename Graph::size_type i = 0; i < diam / 2; ++i) { v = prev[v]; } res.push_back(v); if(diam % 2 == 1) res.push_back(prev[v]); } { auto rest = std::ranges::unique(res); res.erase(std::ranges::begin(rest), std::ranges::end(rest)); } return std::make_pair(diam, res); } template<class Graph> std::size_t tree_hash(const Graph& tree, typename Graph::node_type v, typename Graph::node_type p = -1) { static std::map<std::vector<typename Graph::node_type>, std::size_t> vals; std::vector<typename Graph::node_type> children; for(const auto nv : tree[v]) { if(nv == p) continue; children.emplace_back(tree_hash(tree, nv, v)); } std::ranges::sort(children); if(!vals.contains(children)) { vals[children] = 0; vals[children] = std::ranges::size(vals); } return vals[children]; } } // namespace uni #line 2 "include/hashes.hpp" #line 2 "hash/multiset_hasher.hpp" #line 5 "hash/multiset_hasher.hpp" #line 8 "hash/multiset_hasher.hpp" #line 11 "hash/multiset_hasher.hpp" #line 13 "hash/multiset_hasher.hpp" #line 15 "hash/multiset_hasher.hpp" namespace uni { template<class T, std::uint64_t MOD = 0x1fffffffffffffff, int hasher_id = -1> requires (MOD < std::numeric_limits<std::make_signed_t<std::uint64_t>>::max()) struct multiset_hasher { private: using uint128_t = internal::uint128_t; public: using hash_type = std::uint64_t; using size_type = std::uint64_t; static constexpr hash_type mod = MOD; protected: static inline hash_type _id(const T& v) noexcept(NO_EXCEPT) { return uni::hash64(v); } static constexpr hash_type mask(const size_type a) noexcept(NO_EXCEPT) { return (1ULL << a) - 1; } static constexpr hash_type mul(hash_type a, hash_type b) noexcept(NO_EXCEPT) { #ifdef __SIZEOF_INT128__ uint128_t res = static_cast<uint128_t>(a) * b; #else hash_type a31 = a >> 31, b31 = b >> 31; a &= multiset_hasher::mask(31); b &= multiset_hasher::mask(31); hash_type x = a * b31 + b * a31; hash_type res = (a31 * b31 << 1) + (x >> 30) + ((x & multiset_hasher::mask(30)) << 31) + a * b; #endif res = (res >> 61) + (res & multiset_hasher::mod); if(res >= multiset_hasher::mod) res -= multiset_hasher::mod; return res; } hash_type _hash = 0; inline void _add_hash(const hash_type h, const hash_type count) noexcept(NO_EXCEPT) { this->_hash += multiset_hasher::mul(h, count); if(this->_hash >= multiset_hasher::mod) this->_hash -= multiset_hasher::mod; } inline void _remove_hash(const hash_type h, const hash_type count) noexcept(NO_EXCEPT) { auto hash = to_signed(this->_hash); hash -= multiset_hasher::mul(h, count); if(hash < 0) hash += multiset_hasher::mod; this->_hash = hash; } public: multiset_hasher() noexcept(NO_EXCEPT) {} template<std::input_iterator I, std::sentinel_for<I> S> multiset_hasher(I first, S last) noexcept(NO_EXCEPT) : multiset_hasher() { for(auto itr=first; itr != last; ++itr) this->insert(*itr); } template<class U> multiset_hasher(const std::initializer_list<U>& init_list) noexcept(NO_EXCEPT) : multiset_hasher(std::begin(init_list), std::end(init_list)) {} inline size_type empty() const noexcept(NO_EXCEPT) { return this->get() == 0; } inline void clear() noexcept(NO_EXCEPT) { this->_hash = 0; } // return: whether inserted newly inline void insert(const T& v, size_type count = 1) noexcept(NO_EXCEPT) { this->_add_hash(multiset_hasher::_id(v), count); } // return: iterator of next element erased inline void erase(const T& v, const size_type count = 1) noexcept(NO_EXCEPT) { this->_remove_hash(multiset_hasher::_id(v), count); } inline hash_type get() const noexcept(NO_EXCEPT) { return this->_hash; } inline hash_type operator()() const noexcept(NO_EXCEPT) { return this->_hash; } inline bool operator==(const multiset_hasher& other) const noexcept(NO_EXCEPT) { return this->_hash == other._hash; } inline bool operator!=(const multiset_hasher& other) const noexcept(NO_EXCEPT) { return this->_hash != other._hash; } }; } // namespace uni #line 2 "hash/sequence_hasher.hpp" #line 6 "hash/sequence_hasher.hpp" #include <chrono> #line 11 "hash/sequence_hasher.hpp" #line 15 "hash/sequence_hasher.hpp" #line 18 "hash/sequence_hasher.hpp" #line 20 "hash/sequence_hasher.hpp" #line 22 "hash/sequence_hasher.hpp" namespace uni { // Thanks to: https://github.com/tatyam-prime/kyopro_library/blob/master/RollingHash.cpp template<std::uint64_t MOD = 0x1fffffffffffffff, std::uint64_t BASE = 0> struct sequence_hasher { private: using uint64_t = std::uint64_t; using uint128_t = internal::uint128_t; public: using size_type = internal::size_t; using hash_type = uint64_t; static constexpr hash_type mod = MOD; inline static hash_type base; private: size_type _n = 0, _front = 0; std::vector<hash_type> _hashed; inline static std::vector<hash_type> _powers; protected: static inline hash_type power(const size_type p) noexcept(NO_EXCEPT) { if(static_cast<size_type>(sequence_hasher::_powers.size()) <= p) { size_type n = static_cast<size_type>(sequence_hasher::_powers.size()); sequence_hasher::_powers.resize(p + 1); if(n == 0) sequence_hasher::_powers[0] = 1; REP(i, std::max(size_type{ 0 }, n-1), p) sequence_hasher::_powers[i + 1] = sequence_hasher::mul(sequence_hasher::_powers[i], sequence_hasher::base); } return sequence_hasher::_powers[p]; } inline hash_type& hashed(const size_type p) noexcept(NO_EXCEPT) { if(static_cast<size_type>(this->_hashed.size()) <= p) this->_hashed.resize(p + 1); return this->_hashed[p]; } inline const hash_type& hashed(const size_type p) const noexcept(NO_EXCEPT) { return this->_hashed[p]; } static constexpr hash_type mask(const size_type a) noexcept(NO_EXCEPT) { return (1ULL << a) - 1; } static constexpr hash_type mul(hash_type a, hash_type b) noexcept(NO_EXCEPT) { #ifdef __SIZEOF_INT128__ uint128_t res = static_cast<uint128_t>(a) * b; #else hash_type a31 = a >> 31, b31 = b >> 31; a &= sequence_hasher::mask(31); b &= sequence_hasher::mask(31); hash_type x = a * b31 + b * a31; hash_type res = (a31 * b31 << 1) + (x >> 30) + ((x & sequence_hasher::mask(30)) << 31) + a * b; #endif if constexpr(sequence_hasher::mod == 0x1fffffffffffffff) { res = (res >> 61) + (res & sequence_hasher::mod); if(res >= sequence_hasher::mod) res -= sequence_hasher::mod; } else { res %= sequence_hasher::mod; } return static_cast<hash_type>(res); } size_type index(size_type k) const noexcept(NO_EXCEPT) { return this->_front + k; } public: struct hash { private: const hash_type _val; const size_type _len; public: hash(const hash_type val, const size_type len) noexcept(NO_EXCEPT) : _val(val), _len(len) {} inline hash_type val() const noexcept(NO_EXCEPT) { return this->_val; } inline operator hash_type() const noexcept(NO_EXCEPT) { return this->_val; } inline size_type size() const noexcept(NO_EXCEPT) { return this->_len; } inline bool operator==(const hash& other) const noexcept(NO_EXCEPT) { return this->_val == other._val and this->_len == other._len; } inline bool operator!=(const hash& other) const noexcept(NO_EXCEPT) { return this->_val != other._val or this->_len != other._len; } inline hash concat(const hash& other) const noexcept(NO_EXCEPT) { return sequence_hasher::concat(*this, other); } inline hash operator+(const hash& other) const noexcept(NO_EXCEPT) { return sequence_hasher::concat(*this, other); } }; sequence_hasher(const size_type n = 0) noexcept(NO_EXCEPT) : _n(n) { if(sequence_hasher::base <= 0) { if constexpr(BASE == 0) { sequence_hasher::base = static_cast<hash_type>(uni::primitive_root<true>(sequence_hasher::mod)); } else if constexpr(BASE < 0) { random_engine_64bit random(std::random_device{}()); sequence_hasher::base = static_cast<hash_type>(random() % sequence_hasher::mod); } else { sequence_hasher::base = BASE; } } } template<std::input_iterator I, std::sentinel_for<I> S> sequence_hasher(I first, S last) noexcept(NO_EXCEPT) : sequence_hasher(static_cast<size_type>(std::ranges::distance(first, last))) { this->_hashed.resize(this->_n); this->_hashed.assign(this->_n + 1, 0); size_type i = 0; for(auto itr=first; itr!=last; ++i, ++itr) { this->hashed(i + 1) = sequence_hasher::mul(this->hashed(i), sequence_hasher::base) + *itr; if(this->hashed(i + 1) >= sequence_hasher::mod) this->hashed(i + 1) -= sequence_hasher::mod; } } template<std::ranges::input_range Range> sequence_hasher(Range&& ranges) noexcept(NO_EXCEPT) : sequence_hasher(ALL(ranges)) {} inline size_type size() const noexcept(NO_EXCEPT) { return this->_n - this->_front; } inline hash get(size_type l, size_type r) const noexcept(NO_EXCEPT) { assert(0 <= l and l <= r and r <= this->size()); l = this->index(l), r = this->index(r); hash_type res = this->hashed(r) + sequence_hasher::mod - sequence_hasher::mul(this->hashed(l), sequence_hasher::power(r - l)); if(res >= sequence_hasher::mod) res -= sequence_hasher::mod; return { res, r - l }; } inline hash get() const noexcept(NO_EXCEPT) { return this->get(0, this->size()); } inline hash operator()(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return this->get(l, r); } inline hash subseq(const size_type p, const size_type c) const noexcept(NO_EXCEPT) { return this->get(p, p+c); } inline hash subseq(const size_type p) const noexcept(NO_EXCEPT) { return this->get(p, this->size()); } static constexpr hash_type concat(const hash_type h0, const hash_type h1, const size_type len1) noexcept(NO_EXCEPT) { hash_type res = sequence_hasher::mul(h0, sequence_hasher::power(len1)) + h1; if(res >= sequence_hasher::mod) res -= sequence_hasher::mod; return res; } static constexpr hash concat(const hash& h0, const hash& h1) noexcept(NO_EXCEPT) { return { sequence_hasher::concat(h0.val(), h1.val(), h1.size()), h0.size() + h1.size() }; } template<class T> inline sequence_hasher& push_back(const T& v) noexcept(NO_EXCEPT) { this->_n++; this->hashed(this->_n) = sequence_hasher::mul(this->hashed(this->_n-1), sequence_hasher::base) + hash32(v); if(this->hashed(this->_n) >= sequence_hasher::mod) this->hashed(this->_n-1) -= sequence_hasher::mod; return *this; } inline sequence_hasher& pop_back() noexcept(NO_EXCEPT) { assert(this->_n > 0); this->_n--; return *this; } inline sequence_hasher& pop_front() noexcept(NO_EXCEPT) { this->_front++; assert(this->_front <= this->_n); return *this; } template<std::input_iterator I, std::sentinel_for<I> S> inline sequence_hasher& concat(I first, S last) noexcept(NO_EXCEPT) { size_type n = this->_n; this->_n += std::ranges::distance(first, last); size_type i = n; for(auto itr=first; itr!=last; ++i, ++itr) { this->hashed(i + 1) = sequence_hasher::mul(this->hashed(i), sequence_hasher::base) + *itr; if(this->hashed(i + 1) >= sequence_hasher::mod) this->hashed(i + 1) -= sequence_hasher::mod; } return *this; } template<class T>inline sequence_hasher& concat(const T& v) noexcept(NO_EXCEPT) { return this->concat(ALL(v)); } inline size_type lcp(size_type l0, size_type r0, size_type l1, size_type r1) noexcept(NO_EXCEPT) { size_type size = std::min(r0 - l0, r1 - l1); size_type low = -1, high = size + 1; while(high - low > 1) { size_type mid = (low + high) / 2; if(this->get(l0, l0 + mid) == this->get(l1, l1 + mid)) low = mid; else high = mid; } return low; } }; } // namespace uni #line 2 "hash/set_hasher.hpp" #line 7 "hash/set_hasher.hpp" #line 10 "hash/set_hasher.hpp" #line 12 "hash/set_hasher.hpp" namespace uni { template<class T, int hasher_id = -1, template<class...> class Set = std::unordered_set> struct set_hasher : protected Set<T> { private: using base = Set<T>; public: using hash_type = std::uint64_t; using size_type = typename base::size_type; protected: hash_type _hash = 0; static inline hash_type id(const T& v) noexcept(NO_EXCEPT) { return hash64(v); } public: set_hasher() noexcept(NO_EXCEPT) {} template<std::input_iterator I, std::sentinel_for<I> S> set_hasher(I first, S last) noexcept(NO_EXCEPT) { for(auto itr=first; itr != last; ++itr) this->_insert(*itr); } template<class U> set_hasher(const std::initializer_list<U>& init_list) noexcept(NO_EXCEPT) : set_hasher(std::begin(init_list), std::end(init_list)) {} inline size_type empty() const noexcept(NO_EXCEPT) { return this->base::empty(); } inline size_type size() const noexcept(NO_EXCEPT) { return this->base::size(); } inline size_type max_size() const noexcept(NO_EXCEPT) { return this->base::max_size(); } inline void clear() noexcept(NO_EXCEPT) { this->_hash = 0, this->base::clear(); } using base::count; using base::find; using base::equal_range; inline auto begin() const noexcept(NO_EXCEPT) { return this->base::begin(); } inline auto end() const noexcept(NO_EXCEPT) { return this->base::end(); } template<class... Args> auto lower_bound(const Args&... args) const noexcept(NO_EXCEPT) { return this->base::lower_bound(args...); } template<class... Args> auto upper_bound(const Args&... args) const noexcept(NO_EXCEPT) { return this->base::upper_bound(args...); } // return: whether inserted newly inline bool insert(const T& v) noexcept(NO_EXCEPT) { if(this->base::count(v)) return false; this->base::insert(v); this->_hash ^= set_hasher::id(v); return true; } // return: number of erased elements (0 or 1) inline size_type erase(const T& v) noexcept(NO_EXCEPT) { if(not this->base::count(v)) return 0; this->base::erase(v); this->_hash ^= set_hasher::id(v); return 1; } inline hash_type get() const noexcept(NO_EXCEPT) { return this->_hash; } inline hash_type operator()() const noexcept(NO_EXCEPT) { return this->_hash; } inline bool operator==(const set_hasher& other) const noexcept(NO_EXCEPT) { return this->_hash == other._hash; } inline bool operator!=(const set_hasher& other) const noexcept(NO_EXCEPT) { return this->_hash != other._hash; } }; } // namespace uni #line 2 "include/iterable.hpp" #line 2 "iterable/accumulation.hpp" #line 11 "iterable/accumulation.hpp" #line 14 "iterable/accumulation.hpp" #line 17 "iterable/accumulation.hpp" #line 19 "iterable/accumulation.hpp" namespace uni { template<class T, class Container = vector<T>> struct accumulation : Container { using size_type = internal::size_t; protected: inline size_type _positivize_index(const size_type x) const noexcept(NO_EXCEPT) { return x < 0 ? std::size(*this) + x : x; } public: accumulation() noexcept(NO_EXCEPT) {} template<std::ranges::input_range R, class Operator = std::plus<T>> requires std::regular_invocable<Operator, T, T> explicit accumulation(R&& range, const T& head = T(), Operator&& op = std::plus<T>{}) : accumulation(ALL(range), head, op) {} template< std::input_iterator I, std::sentinel_for<I> S, class Operator = std::plus<T> > accumulation(I first, S last, const T& head = T(), Operator&& op = std::plus<T>{}) noexcept(NO_EXCEPT) { this->resize(std::ranges::distance(first, last) + 1); *this->begin() = head; for(auto itr = std::ranges::begin(*this); first != last; ++first) { const auto prev = itr++; *itr = op(*prev, *first); } } template<class Operator = std::minus<T>> requires std::regular_invocable<Operator, T, T> T operator()(size_type left, size_type right, Operator&& op = std::minus<T>{}) noexcept(NO_EXCEPT) { left = _positivize_index(left), right = _positivize_index(right); assert(0 <= left and left <= right and right < (size_type)std::size(*this)); return op((*this)[right], (*this)[left]); } template<class Operator = std::minus<T>> requires std::regular_invocable<Operator, T, T> T operator()(size_type left, size_type right, Operator&& op = std::minus<T>{}) const noexcept(NO_EXCEPT) { left = _positivize_index(left), right = _positivize_index(right); assert(0 <= left and left <= right and right < (size_type)std::size(*this)); return op(this->at(right), this->at(left)); } }; template<std::input_iterator I, std::sentinel_for<I> S> explicit accumulation(I, S) -> accumulation<typename std::iterator_traits<I>::value_type>; template<std::ranges::input_range R> explicit accumulation(R&&) -> accumulation<typename std::ranges::range_value_t<R>>; template<class T, class Container = vector<vector<T>>, class Operator = std::plus<T>> struct accumulation_2d : Container { using size_type = internal::size_t; protected: inline size_type _positivize_index(const size_type x) const noexcept(NO_EXCEPT) { return x < 0 ? std::size(*this) + x : x; } Operator _op; public: accumulation_2d() noexcept(NO_EXCEPT) {} template<std::ranges::input_range R> requires std::ranges::input_range<typename std::ranges::range_value_t<R>> && std::regular_invocable<Operator, T, T> explicit accumulation_2d(R&& range, const T& head = T(), Operator&& op = std::plus<T>{}) : accumulation_2d(ALL(range), head, op) {} template<std::input_iterator I, std::sentinel_for<I> S> accumulation_2d(I first, S last, const T head = T{}, const Operator op = std::plus<T>{}) noexcept(NO_EXCEPT) : _op(op) { const auto h = static_cast<size_type>(std::ranges::distance(first, last)); const auto w = static_cast<size_type>(std::ranges::distance(ALL(*first))); { auto row = first; this->assign(h + 1, {}); (*this)[0].assign(w + 1, head); REP(i, h) { assert(w == std::ranges::ssize(*row)); (*this)[i + 1].assign(w + 1, head); REP(j, w) (*this)[i + 1][j + 1] = first[i][j]; ++row; } } FOR(i, 1, h) FOR(j, w) (*this)[i][j] = op((*this)[i][j], (*this)[i - 1][j]); FOR(i, h) FOR(j, 1, w) (*this)[i][j] = op((*this)[i][j], (*this)[i][j - 1]); } template<class Rev = std::minus<T>> inline T operator()(size_type a, size_type b, size_type c, size_type d, const Rev rev = std::minus<T>{}) const noexcept(NO_EXCEPT) { a = _positivize_index(a), b = _positivize_index(b); c = _positivize_index(c), d = _positivize_index(d); assert(0 <= a and a <= b and b < (size_type)std::size(*this)); assert(0 <= c and c <= d and d < (size_type)std::size((*this)[0])); return this->_op(rev((*this)[b][d], this->_op((*this)[a][d], (*this)[b][c])), (*this)[a][c]); } template<class Rev = std::minus<T>> inline T operator()(const std::pair<size_type,size_type> p, const std::pair<size_type,size_type> q, const Rev rev = std::minus<T>{}) const noexcept(NO_EXCEPT) { return this->operator()(p.first, p.second, q.first, q.second, rev); } }; template<std::input_iterator I, std::sentinel_for<I> S> explicit accumulation_2d(I, S) -> accumulation_2d< typename std::iterator_traits<typename std::ranges::iterator_t<typename std::iterator_traits<I>::value_type>>::value_type >; template<std::input_iterator I, std::sentinel_for<I> S> explicit accumulation_2d(I, S) -> accumulation_2d< typename std::iterator_traits<typename uni::internal::iterator_t<typename std::iterator_traits<I>::value_type>>::value_type >; template<std::ranges::input_range R> requires std::ranges::input_range<typename std::ranges::range_value_t<R>> explicit accumulation_2d(R&&) -> accumulation_2d< typename std::ranges::range_value_t<typename std::ranges::range_value_t<R>> >; } // namespace uni #line 2 "iterable/adjacent_difference.hpp" #line 8 "iterable/adjacent_difference.hpp" #line 11 "iterable/adjacent_difference.hpp" #line 13 "iterable/adjacent_difference.hpp" namespace uni { template<class T, class container = valarray<T>> struct adjacent_difference : container { public: explicit adjacent_difference() noexcept(NO_EXCEPT) {} template< std::input_iterator I, std::sentinel_for<I> S, class Operator = std::minus<T> > explicit adjacent_difference(I first, S last, const bool remove_first = true, const Operator op = std::minus<T>{}) noexcept(NO_EXCEPT) { this->resize(std::ranges::distance(first, last)); std::vector<T> diff(this->size()); std::adjacent_difference(first, last, std::ranges::begin(diff), op); if(remove_first) diff.erase(std::ranges::begin(diff)); this->assign(std::ranges::begin(diff), std::ranges::end(diff)); } }; template<std::input_iterator I, std::sentinel_for<I> S> explicit adjacent_difference(I, S) -> adjacent_difference<typename std::iterator_traits<I>::value_type>; } // namespace uni #line 2 "iterable/applied.hpp" #line 8 "iterable/applied.hpp" #line 10 "iterable/applied.hpp" #line 12 "iterable/applied.hpp" namespace uni { template<std::ranges::range R, class F> inline R applied(R v, F&& func) noexcept(NO_EXCEPT) { func(std::ranges::begin(v), std::ranges::end(v)); return v; } template<std::ranges::range R> inline auto sorted(R&& v) noexcept(NO_EXCEPT) { return applied(std::forward<R>(v), std::ranges::sort); } template<std::ranges::range R> inline auto reversed(R&& v) noexcept(NO_EXCEPT) { return applied(std::forward<R>(v), std::ranges::reverse); } } // namespace uni #line 2 "iterable/count_inversion.hpp" #line 7 "iterable/count_inversion.hpp" #line 9 "iterable/count_inversion.hpp" #line 12 "iterable/count_inversion.hpp" #line 14 "iterable/count_inversion.hpp" #line 17 "iterable/count_inversion.hpp" namespace uni { template<const bool STRICT = true, class T = std::int64_t> struct inversion { template<std::input_iterator I, std::sentinel_for<I> S> static inline T count(I first, S last) noexcept(NO_EXCEPT) { const internal::size_t n = std::distance(first, last); const auto [ min, max ] = std::minmax_element(first, last); const auto m = *max - *min + 1; fenwick_tree<actions::range_sum<T>> cnt(m); T res = 0; { internal::size_t i = 0; I itr = first; for(; i < n; ++i, ++itr) { res += cnt(*itr - *min + STRICT, m).fold().val(); cnt[*itr - *min] += 1; } } return res; } template<std::ranges::input_range R> static inline T count(R&& range) noexcept(NO_EXCEPT) { return inversion::count(ALL(range)); } template<std::input_iterator I, std::sentinel_for<I> S> static inline T count_with_compression(I first, S last) noexcept(NO_EXCEPT) { compressed<typename std::iterator_traits<I>::value_type> comp(first, last); return inversion::count(comp); } template<std::ranges::input_range R> static inline T count_with_compression(R&& range) noexcept(NO_EXCEPT) { return inversion::count_with_compression(ALL(range)); } }; } // namespace uni #line 2 "iterable/counter.hpp" #line 4 "iterable/counter.hpp" #line 8 "iterable/counter.hpp" #line 10 "iterable/counter.hpp" namespace uni { template<class T, class Container = dynamic_auto_holder<T, internal::size_t>> struct counter : Container { counter() noexcept(NO_EXCEPT) = default; template<std::input_iterator I, std::sentinel_for<I> S> counter(I first, S last) noexcept(NO_EXCEPT) { for(auto itr = first; itr != last; ++itr) ++(*this)[*itr]; } template<std::ranges::input_range R> explicit counter(R&& range) noexcept(NO_EXCEPT) : counter(ALL(range)) {} }; template<std::input_iterator I, std::sentinel_for<I> S> explicit counter(I, S) -> counter<std::iter_value_t<I>>; template<std::ranges::input_range R> explicit counter(R) -> counter<std::ranges::range_value_t<R>>; } // namespace uni #line 2 "iterable/inverse.hpp" #line 6 "iterable/inverse.hpp" #line 10 "iterable/inverse.hpp" #line 12 "iterable/inverse.hpp" #line 14 "iterable/inverse.hpp" namespace uni { template<class T, class V = vector<internal::size_t>, class container = dynamic_auto_holder<T, V>> struct inverse : container { explicit inverse() noexcept(NO_EXCEPT) {} template<std::ranges::input_range R> inverse(R&& range) noexcept(NO_EXCEPT) : inverse(std::ranges::begin(range), std::ranges::end(range)) {} template<std::input_iterator I, std::sentinel_for<I> S> inverse(I first, S last) noexcept(NO_EXCEPT) { typename V::value_type index = 0; for(auto itr = first; itr != last; ++itr, ++index) (*this)[*itr].emplace_back(index); } }; template<std::input_iterator I, std::sentinel_for<I> S> explicit inverse(I, S) -> inverse<typename std::iterator_traits<I>::value_type>; template<std::ranges::input_range R> explicit inverse(R&&) -> inverse<std::ranges::range_value_t<R>>; } // namespace uni #line 2 "iterable/longest_common_subsequence.hpp" #line 7 "iterable/longest_common_subsequence.hpp" #line 10 "iterable/longest_common_subsequence.hpp" #line 13 "iterable/longest_common_subsequence.hpp" #line 15 "iterable/longest_common_subsequence.hpp" namespace uni { template<class container = grid<internal::size_t>> struct lcs_sizes : container { lcs_sizes() noexcept = default; template<std::ranges::input_range R0, std::ranges::input_range R1> lcs_sizes(R0&& r0, R1&& r1) noexcept(NO_EXCEPT) : container(ALL(r0), ALL(r1)) {} template< std::input_iterator I0, std::input_iterator I1, std::sentinel_for<I0> S0, std::sentinel_for<I1> S1 > lcs_sizes(I0 first0, S0 last0, I1 first1, S1 last1) noexcept(NO_EXCEPT) : container(std::ranges::distance(first0, last0) + 1, std::ranges::distance(first1, last1) + 1) { internal::size_t pos0 = 0; for(auto itr0=first0; itr0!=last0; ++pos0, ++itr0) { internal::size_t pos1 = 0; for(auto itr1=first1; itr1!=last1; ++pos1, ++itr1) { if(*itr0 == *itr1) (*this)(pos0 + 1, pos1 + 1) = (*this)(pos0, pos1) + 1; else (*this)(pos0 + 1, pos1 + 1) = std::max((*this)(pos0 + 1, pos1), (*this)(pos0, pos1 + 1)); } } } }; } // namespace uni #line 2 "iterable/longest_increasing_subsequence.hpp" #line 6 "iterable/longest_increasing_subsequence.hpp" #line 9 "iterable/longest_increasing_subsequence.hpp" #line 12 "iterable/longest_increasing_subsequence.hpp" #line 14 "iterable/longest_increasing_subsequence.hpp" #line 16 "iterable/longest_increasing_subsequence.hpp" namespace uni { template<bool STRICT, class T, class container = vector<T>> struct lis : container { using size_type = typename internal::size_t; std::vector<size_type> indices, positions; lis() noexcept = default; template<std::ranges::input_range R> explicit lis(R&& range) noexcept(NO_EXCEPT) : lis(ALL(range)) {} template<std::input_iterator I, std::sentinel_for<I> S> lis(I first, S last) noexcept(NO_EXCEPT) : positions(std::ranges::distance(first, last), -1) { this->reserve(std::ranges::distance(first, last)); size_type pos = 0; for(auto itr=first; itr!=last; ++pos, ++itr) { typename container::iterator bound; if constexpr(STRICT) bound = std::ranges::lower_bound(*this, *itr); else bound = std::ranges::upper_bound(*this, *itr); this->positions[pos] = static_cast<size_type>(std::ranges::distance(std::ranges::begin(*this), bound)); if(std::ranges::end(*this) == bound) this->emplace_back(*itr); else *bound = *itr; } size_type target = std::ranges::max(this->positions); for(size_type i = static_cast<size_type>(this->positions.size()); --i >= 0;){ if(this->positions[i] == target) { this->operator[](target) = *(first + i); this->indices.emplace_back(i); --target; } } std::ranges::reverse(this->indices); } }; } // namespace uni #line 2 "iterable/run_length_encoding.hpp" #line 8 "iterable/run_length_encoding.hpp" #line 12 "iterable/run_length_encoding.hpp" #line 14 "iterable/run_length_encoding.hpp" namespace uni { template<class T, class container = vector<std::pair<T,internal::size_t>>> struct run_length : container { run_length() noexcept(NO_EXCEPT) = default; template<std::input_iterator I, std::sentinel_for<I> S> run_length(I first, S last) noexcept(NO_EXCEPT) { this->clear(); typename container::value_type::second_type cnt = 0; for(I itr=first, prev=itr; itr!=last; ++itr) { if(*prev != *itr) this->emplace_back(*prev, cnt), cnt = 0; ++cnt; prev = itr; } this->emplace_back(*std::ranges::prev(last), cnt); } template<std::ranges::input_range R> explicit run_length(R&& range) : run_length(ALL(range)) {}; }; template<std::input_iterator I, std::sentinel_for<I> S> run_length(I, S) -> run_length<std::iter_value_t<I>>; template<std::ranges::input_range R> explicit run_length(R&& range) -> run_length<std::ranges::range_value_t<R>>; } // namespace uni #line 2 "include/numeric.hpp" #line 9 "include/numeric.hpp" #line 2 "numeric/binomial_coefficient.hpp" #line 6 "numeric/binomial_coefficient.hpp" #line 9 "numeric/binomial_coefficient.hpp" #line 13 "numeric/binomial_coefficient.hpp" #line 18 "numeric/binomial_coefficient.hpp" // Thanks to: https://nyaannyaan.github.io/library/modulo/arbitrary-mod-binomial.hpp namespace uni { namespace internal { template<class T, class R = T, class Reduction = barrett_reduction_32bit> requires (std::numeric_limits<R>::digits > 30) || modint_family<R> struct binomial_coefficient_prime_power_mod { using value_type = T; using mod_type = R; static constexpr i64 MOD_SUP = (i64{1} << 30) - 1; static constexpr u32 MAX_BUFFER_SIZE = 30'000'000; private: using self = binomial_coefficient_prime_power_mod; using reduction = Reduction; u32 _p, _q, _m; value_type _max; std::valarray<u32> _fact, _inv_fact, _inv; u32 _delta; barrett_reduction_32bit _barrett_m, _barrett_p; reduction _reduction_m; u32 _one; static constexpr std::pair<u32,u32> _factorize(u32 m) { for(u32 i=2; i*i<=m; ++i) { if(m % i == 0) { u32 cnt = 0; while(m % i == 0) m /= i, ++cnt; assert(m == 1); return { i, cnt }; } } return { m, 1 }; } void _init() { const u32 size = std::min(this->_m, static_cast<u32>(this->_max) + 1); assert(size < self::MAX_BUFFER_SIZE); this->_barrett_m = barrett_reduction_32bit(this->_m); this->_barrett_p = barrett_reduction_32bit(this->_p); this->_reduction_m = self::reduction(this->_m); this->_delta = this->_reduction_m.convert_raw((this->_p == 2 && this->_q >= 3) ? 1 : this->_m - 1); this->_one = this->_reduction_m.convert_raw(1); this->_fact.resize(size); this->_inv_fact.resize(size); this->_inv.resize(size); this->_fact[0] = this->_inv_fact[0] = this->_inv[0] = this->_one; this->_fact[1] = this->_inv_fact[1] = this->_inv[1] = this->_one; REP(i, 2, size) { if(this->_barrett_p.reduce(i) == 0) { this->_fact[i] = this->_fact[i - 1]; this->_fact[i + 1] = this->_reduction_m.multiply(this->_fact[i - 1], this->_reduction_m.convert_raw(this->_barrett_m.reduce(i + 1))); ++i; } else { this->_fact[i] = this->_reduction_m.multiply(this->_fact[i - 1], this->_reduction_m.convert_raw(this->_barrett_m.reduce(i))); } } this->_inv_fact[size - 1] = this->_reduction_m.pow(this->_fact[size - 1], this->_m / this->_p * (this->_p - 1) - 1); REPD(i, 2, size - 1) { this->_inv_fact[i] = this->_reduction_m.multiply(this->_inv_fact[i + 1], this->_reduction_m.convert_raw(this->_barrett_m.reduce(i + 1))); if(this->_barrett_p.reduce(i) == 0) { this->_inv_fact[i - 1] = this->_inv_fact[i]; --i; } } } public: binomial_coefficient_prime_power_mod() noexcept = default; explicit binomial_coefficient_prime_power_mod(const value_type max = 20'000'000) noexcept(NO_EXCEPT) requires (1 < mod_type::mod() && mod_type::mod() < self::MOD_SUP) : _m(mod_type::mod()), _max(max) { constexpr std::pair<u32,u32> pq = self::_factorize(mod_type::mod()); std::tie(this->_p, this->_q) = pq; this->_init(); } explicit binomial_coefficient_prime_power_mod(const mod_type p, mod_type q = 1, const value_type max = 20'000'000) noexcept(NO_EXCEPT) requires (not modint_family<mod_type>) : _p(static_cast<u32>(p)), _q(static_cast<u32>(q)), _max(max) { assert(1 < p && p < self::MOD_SUP); assert(0 < q); u64 m = 1; while(q--) { m *= this->_p; assert(m < MOD_SUP); } this->_m = static_cast<u32>(m); this->_init(); } inline mod_type mod() const noexcept(NO_EXCEPT) { return this->_m; } mod_type lucus(value_type n, value_type r) const noexcept(NO_EXCEPT) { assert(0 <= n); assert(0 <= r); if(n < r) return 0; u32 res = this->_one; while(n > 0) { u32 n0, k0; std::tie(n, n0) = this->_barrett_p.divide(n); std::tie(r, k0) = this->_barrett_p.divide(r); if(n0 < k0) return 0; res = this->_reduction_m.multiply(res, this->_fact[n0]); res = this->_reduction_m.multiply(res, this->_reduction_m.multiply(this->_inv_fact[n0 - k0], this->_inv_fact[k0])); } return static_cast<mod_type>(this->_reduction_m.revert(res)); } mod_type comb(value_type n, value_type r) const noexcept(NO_EXCEPT) { assert(0 <= n); assert(0 <= r); if(this->_q == 1) return this->lucus(n, r); if(n < r) return 0; value_type k = n - r; u32 e0 = 0, eq = 0, i = 0; u32 res = this->_one; while(n > 0) { res = this->_reduction_m.multiply(res, this->_fact[this->_barrett_m.reduce(n)]); res = this->_reduction_m.multiply(res, this->_inv_fact[this->_barrett_m.reduce(r)]); res = this->_reduction_m.multiply(res, this->_inv_fact[this->_barrett_m.reduce(k)]); n = this->_barrett_p.quotient(n); r = this->_barrett_p.quotient(r); k = this->_barrett_p.quotient(k); u32 eps = static_cast<u32>(n - r - k); e0 += eps; if(e0 >= this->_q) return 0; if(++i >= this->_q) eq += eps; } if(eq & 1) res = this->_reduction_m.multiply(res, this->_delta); res = this->_reduction_m.multiply(res, this->_reduction_m.pow(this->_reduction_m.convert_raw(this->_p), e0)); return static_cast<mod_type>(this->_reduction_m.revert(res)); } }; } // namespace internal using internal::binomial_coefficient_prime_power_mod; // (md < 10^7 && N < 2^30) || (md < 2^30 && N < 2 * 10^7) template<class T, class R = T> requires (std::numeric_limits<R>::digits > 30) || internal::modint_family<R> struct binomial_coefficient { using value_type = T; using mod_type = R; private: template<class reduction = montgomery_reduction_32bit> using internal_binomial = internal::binomial_coefficient_prime_power_mod<value_type, long long, reduction>; u32 _mod; value_type _max; std::vector<u32> _mods; std::vector<internal_binomial<>> _internals; internal_binomial<binary_reduction_32bit> _internal_2p; void _init() noexcept(NO_EXCEPT) { u32 md = this->_mod; if(md == 1) return; assert((md < 20'000'000 && this->_max < (1 << 30)) || (md < (1 << 30) && this->_max < 30'000'000)); assert(1 <= md); assert(md <= internal_binomial<>::MOD_SUP); for(u32 i=2; i*i<=md; ++i) { if(md % i == 0) { u32 j = 0, k = 1; while(md % i == 0) md /= i, ++j, k *= i; this->_mods.push_back(k); if(i == 2) { this->_internal_2p = internal_binomial<binary_reduction_32bit>(2, j, this->_max); this->_internals.emplace_back(); } else { this->_internals.emplace_back(i, j, this->_max); assert(this->_mods.back() == this->_internals.back().mod()); } } } if(md != 1) { this->_mods.push_back(static_cast<u32>(md)); if(md == 2) this->_internal_2p = internal_binomial<binary_reduction_32bit>(2, 1, this->_max); else this->_internals.emplace_back(md, 1, this->_max); } } public: binomial_coefficient(const value_type max = 20'000'000) noexcept(NO_EXCEPT) requires internal::modint_family<mod_type> : _mod(static_cast<u32>(mod_type::mod())), _max(max) { this->_init(); } binomial_coefficient(const mod_type mod, const value_type max = 20'000'000) noexcept(NO_EXCEPT) requires (not internal::modint_family<mod_type>) : _mod(static_cast<u32>(mod)), _max(max) { this->_init(); } mod_type comb(const value_type n, const value_type r) const noexcept(NO_EXCEPT) { assert(n >= 0), assert(r >= 0); if(this->_mod == 1) return 0; if(n < r) return 0; if(this->_mods.size() == 1) { if((this->_mods.back() & 1) == 0) return static_cast<mod_type>(this->_internal_2p.comb(n, r)); else return static_cast<mod_type>(this->_internals[0].comb(n, r)); } std::vector<long long> rem, div; REP(i, 0, std::ranges::ssize(this->_mods)) { div.push_back(this->_mods[i]); if((this->_mods[i] & 1) == 0) rem.push_back(this->_internal_2p.comb(n, r)); else { rem.push_back(this->_internals[i].comb(n, r)); } } return static_cast<mod_type>(atcoder::crt(rem, div).first); } }; } // namespace uni #line 2 "numeric/boundary_seeker.hpp" #line 8 "numeric/boundary_seeker.hpp" #line 11 "numeric/boundary_seeker.hpp" #line 14 "numeric/boundary_seeker.hpp" #line 16 "numeric/boundary_seeker.hpp" namespace uni { namespace internal { namespace boundary_seeker_impl { template<class T> struct integal { protected: std::function<bool(T)> _validate; public: integal(std::function<bool(T)> validate) noexcept(NO_EXCEPT) : _validate(validate) {} template<bool INVERT = false> T bound(const T _ok, const T _ng) const noexcept(NO_EXCEPT) { T ok = _ok, ng = _ng; if constexpr(INVERT) std::swap(ng, ok); while(std::abs(ok - ng) > 1) { T mid = ng + (ok - ng) / 2; (INVERT ^ this->_validate(mid) ? ok : ng) = mid; } return ok; } template<bool REVERSE = false, bool INVERT = false> T bound(const T ok) const noexcept(NO_EXCEPT) { assert(INVERT ^ this->_validate(ok)); T ng = REVERSE ? -1 : 1; while(INVERT ^ this->_validate(ok + ng)) ng += ng; return this->bound<INVERT>(ok, ok + ng); } template<bool REVERSE = false, bool INVERT = false> T bound() const noexcept(NO_EXCEPT) { return this->bound<INVERT>( REVERSE ? numeric_limits<T>::arithmetic_infinity() / 2 : numeric_limits<T>::arithmetic_negative_infinity() / 2 ); } template<bool INVERT = false> T bound_or(const T ok, const T ng, const T proxy) const noexcept(NO_EXCEPT) { const T res = this->bound<INVERT>(ok, ng); return this->_validate(res) ? res : proxy; } template<bool REVERSE = false, bool INVERT = false> T bound_or(const T ok, const T proxy) const noexcept(NO_EXCEPT) { const T res = this->bound<REVERSE, INVERT>(ok); return this->_validate(res) ? res : proxy; } template<bool REVERSE = false, bool INVERT = false> T bound_or(const T proxy) const noexcept(NO_EXCEPT) { const T res = this->bound<REVERSE, INVERT>(); return this->_validate(res) ? res : proxy; } }; template<class T> struct floating_point { protected: std::function<bool(T)> _validate; public: floating_point(std::function<bool(T)> validate) noexcept(NO_EXCEPT) : _validate(validate) {} template<bool INVERT = false, internal::size_t ITERATIONS = 200> T bound(const T _ok, const T _ng) const noexcept(NO_EXCEPT) { T ok = _ok, ng = _ng; if constexpr(INVERT) std::swap(ng, ok); REP(ITERATIONS) { T mid = ng + (ok - ng) / 2; (INVERT ^ this->_validate(mid) ? ok : ng) = mid; } return ok; } template<bool REVERSE = false, bool INVERT = false, internal::size_t ITERATIONS = 200> T bound(const T ok) const noexcept(NO_EXCEPT) { assert(INVERT ^ this->_validate(ok)); T ng = REVERSE ? -1 : 1; while(INVERT ^ this->_validate(ok + ng)) ng += ng; return this->bound<INVERT>(ok, ok + ng); } template<bool REVERSE = false, bool INVERT = false, internal::size_t ITERATIONS = 200> T bound() const noexcept(NO_EXCEPT) { return this->bound<INVERT, ITERATIONS>( REVERSE ? numeric_limits<T>::arithmetic_infinity() / 2 : numeric_limits<T>::arithmetic_negative_infinity() / 2 ); } template<bool INVERT = false, internal::size_t ITERATIONS = 200> T bound_or(const T ok, const T ng, const T proxy) const noexcept(NO_EXCEPT) { const T res = this->bound<INVERT, ITERATIONS>(ok, ng); return this->_validate(res) ? res : proxy; } template<bool REVERSE = false, bool INVERT = false, internal::size_t ITERATIONS = 200> T bound_or(const T ok, const T proxy) const noexcept(NO_EXCEPT) { const T res = this->bound<REVERSE, INVERT, ITERATIONS>(ok); return this->_validate(res) ? res : proxy; } template<bool REVERSE = false, bool INVERT = false, internal::size_t ITERATIONS = 200> T bound_or(const T proxy) const noexcept(NO_EXCEPT) { const T res = this->bound<REVERSE, INVERT, ITERATIONS>(); return this->_validate(res) ? res : proxy; } }; template<class, bool> struct seeker {}; template<class T> struct seeker<T,true> : integal<T> { using integal<T>::integal; }; template<class T> struct seeker<T,false> : floating_point<T> { using floating_point<T>::floating_point; }; } // namespace boundary_seeker_impl } // namespace internal template<class T> using boundary_seeker = internal::boundary_seeker_impl::seeker<T,std::is_integral_v<T>>; } // namespace uni #line 2 "numeric/divisors.hpp" #line 5 "numeric/divisors.hpp" #line 8 "numeric/divisors.hpp" namespace uni { template<class T> vector<T> divisors_sieve(const T k) noexcept(NO_EXCEPT) { vector<T> res; for(T i=1; i*i<=k; ++i) { if(k%i == 0) { res.emplace_back(i); if(i*i < k) res.emplace_back(k/i); } } res.sort(); return res; } } // namespace uni #line 2 "numeric/extremum_seeker.hpp" #line 6 "numeric/extremum_seeker.hpp" #line 10 "numeric/extremum_seeker.hpp" #line 13 "numeric/extremum_seeker.hpp" #line 15 "numeric/extremum_seeker.hpp" #line 17 "numeric/extremum_seeker.hpp" namespace uni { template<class Signature> struct extremum_seeker; template<class T, std::floating_point Arg> struct extremum_seeker<T(Arg)> { using value_type = T; using arg_type = Arg; private: std::function<T(Arg)> _f; template<const internal::size_t ITERATIONS> std::pair<arg_type, arg_type> search(arg_type low, arg_type high, const auto comp) const noexcept(NO_EXCEPT) { REP(ITERATIONS) { const auto p = low + (high - low) / 3; const auto q = high - (high - low) / 3; if(comp(p, q)) high = q; else low = p; } return { low, high }; } public: template<class F> requires std::same_as<std::invoke_result_t<F, Arg>, T> extremum_seeker(F&& f) noexcept(NO_EXCEPT) : _f(std::forward<F>(f)) {}; template<const internal::size_t ITERATIONS = 100'000> std::pair<arg_type, arg_type> arg_min( arg_type low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), arg_type high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) const noexcept(NO_EXCEPT) { const auto comp = [&](const arg_type lhs, const arg_type rhs) noexcept(NO_EXCEPT) { return this->_f(lhs) < this->_f(rhs); }; return this->search<ITERATIONS>(low, high, comp); } template<const internal::size_t ITERATIONS = 100'000> std::pair<arg_type, arg_type> arg_max( arg_type low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), arg_type high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) const noexcept(NO_EXCEPT) { const auto comp = [&](const arg_type lhs, const arg_type rhs) noexcept(NO_EXCEPT) { return this->_f(lhs) > this->_f(rhs); }; return this->search<ITERATIONS>(low, high, comp); } template<const internal::size_t ITERATIONS = 100'000> auto min( const arg_type _low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), const arg_type _high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) const noexcept(NO_EXCEPT) { const auto [ low, high ] = this->arg_min<ITERATIONS>(_low, _high); auto res = std::min(this->_f(low), this->_f(high)); FOR(x, low, high) chmin(res, this->_f(x)); return res; } template<const internal::size_t ITERATIONS = 100'000> auto max( const arg_type _low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), const arg_type _high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) const noexcept(NO_EXCEPT) { const auto [ low, high ] = this->arg_max<ITERATIONS>(_low, _high); auto res = std::max(this->_f(low), this->_f(high)); FOR(x, low, high) chmax(res, this->_f(x)); return res; } }; template<class T, std::integral Arg> struct extremum_seeker<T(Arg)> { using value_type = T; using arg_type = Arg; private: std::function<T(Arg)> _f; std::vector<arg_type> _fib = { 0, 1 }; gnu::gp_hash_table<arg_type, value_type> _cache; auto _expand(const arg_type size) noexcept(NO_EXCEPT) { assert(size >= 0); this->_fib.reserve(std::bit_width(to_unsigned(size))); if(this->_fib.back() < size) { do { this->_fib.emplace_back( this->_fib[std::ranges::size(this->_fib) - 1] + this->_fib[std::ranges::size(this->_fib) - 2] ); } while(this->_fib.back() < size); return std::ranges::prev(this->_fib.end()); } return std::ranges::lower_bound(this->_fib, size); } auto _func(const arg_type size) noexcept(NO_EXCEPT) { if(this->_cache.contains(size)) return this->_cache[size]; return this->_cache[size] = this->_f(size); } auto _search(arg_type low, const arg_type high, const auto comp) noexcept(NO_EXCEPT) { if(low == high) return low; auto _low = low - 1; const auto itr = this->_expand(high - _low + 1); auto _high = *itr + _low; auto diff = *std::ranges::prev(itr); while(true) { const auto p = _high - diff; const auto q = _low + diff; if(p == q) return p; if(comp(p, q)) _high = q; else _low = p; diff = diff - (q - p); } } public: template<class F> requires std::same_as<std::invoke_result_t<F, Arg>, T> extremum_seeker(F&& f, const arg_type init_size = 0) noexcept(NO_EXCEPT) : _f(std::forward<F>(f)) { this->_expand(init_size); } auto arg_min( const arg_type low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), const arg_type high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) noexcept(NO_EXCEPT) { const auto comp = [&](const arg_type lhs, const arg_type rhs) noexcept(NO_EXCEPT) { if(high < rhs) return true; return this->_func(lhs) < this->_func(rhs); }; return this->_search(low, high, comp); } auto arg_max( const arg_type low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), const arg_type high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) noexcept(NO_EXCEPT) { const auto comp = [&](const arg_type lhs, const arg_type rhs) noexcept(NO_EXCEPT) { if(high < rhs) return true; return this->_func(lhs) > this->_func(rhs); }; return this->_search(low, high, comp); } inline auto min( const arg_type _low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), const arg_type high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) noexcept(NO_EXCEPT) { return this->_func(this->arg_min(_low, high)); } inline auto max( const arg_type _low = uni::numeric_limits<arg_type>::arithmetic_negative_infinity(), const arg_type high = uni::numeric_limits<arg_type>::arithmetic_infinity() ) noexcept(NO_EXCEPT) { return this->_func(this->arg_max(_low, high)); } }; } // namespace uni #line 2 "numeric/factorial.hpp" #line 5 "numeric/factorial.hpp" #line 7 "numeric/factorial.hpp" #line 9 "numeric/factorial.hpp" #line 11 "numeric/factorial.hpp" namespace uni { namespace internal { template<class T> struct factorial_base { using value_type = T; using size_type = internal::size_t; static constexpr value_type calc(const size_type& n) noexcept(NO_EXCEPT) { assert(n >= 0); value_type ans = 1; FOR(k, 1, n) ans *= k; return ans; } }; } // namespace internal template<class> struct factorial {}; template<std::integral T> struct factorial<T> : internal::factorial_base<T> { using value_type = T; using size_type = internal::size_t; private: size_type _n; std::valarray<value_type> _fact; public: factorial(const size_type n) noexcept(NO_EXCEPT) : _n(n), _fact(n + 1) { this->_fact[0] = this->_fact[1] = 1; FOR(i, 2, n) this->_fact[i] = this->_fact[i - 1] * i; } inline value_type fact(const size_type k) noexcept(NO_EXCEPT) { assert(0 <= k and k <= this->_n); return this->_fact[k]; } inline value_type operator()(const size_type k) noexcept(NO_EXCEPT) { return this->fact(k); } auto _debug() const { return this->_fact; } }; template<uni::internal::modint_family T> struct factorial<T> : internal::factorial_base<T> { using value_type = T; using size_type = internal::size_t; private: size_type _n; std::valarray<value_type> _fact, _ifact, _inv; public: factorial(const size_type n) noexcept(NO_EXCEPT) : _n(n), _fact(n + 1), _ifact(n + 1), _inv(n + 1) { constexpr auto P = T::mod(); this->_fact[0] = this->_fact[1] = 1; this->_ifact[0] = this->_ifact[1] = 1; this->_inv[1] = 1; FOR(i, 2, n) { this->_inv[i] = -this->_inv[P % i] * (P / i); this->_fact[i] = this->_fact[i - 1] * i; this->_ifact[i] = this->_ifact[i - 1] * this->_inv[i]; } } inline value_type fact(const size_type k) noexcept(NO_EXCEPT) { assert(0 <= k and k <= this->_n); return this->_fact[k]; } inline value_type operator()(const size_type k) noexcept(NO_EXCEPT) { return this->fact(k); } inline value_type ifact(const size_type k) noexcept(NO_EXCEPT) { assert(0 <= k and k <= this->_n); return this->_ifact[k]; } inline value_type inv(const size_type k) noexcept(NO_EXCEPT) { assert(0 <= k and k <= this->_n); return this->_inv[k]; } inline value_type bimom(const size_type n, const size_type r) noexcept(NO_EXCEPT) { assert(0 <= r and r <= n and n <= this->_n); return this->fact(n) * this->ifact(r) * this->ifact(n - r); } auto _debug() const { return this->_fact; } }; } // namespace uni #line 2 "numeric/hilbert_order.hpp" #line 4 "numeric/hilbert_order.hpp" template<class T> T hilbert_order(const T n, T i, T j) { T p, q, d = 0; for(T t=n>>1; t>0; t>>=1) { p = (i&t) > 0, q = (j&t) > 0; d += t * t * ((p * 3) ^ q); if(q > 0) continue; if(p > 0) { i = n - i - 1; j = n - j - 1; } std::swap(i, j); } return d; } template<class T> T hilbert_order(const T n,const std::pair<T,T> p) { return hilbert_order(n, p.first, p.second); } #line 2 "numeric/interval_scanner.hpp" #line 2 "numeric/internal/two_pointer_technique.hpp" #line 10 "numeric/internal/two_pointer_technique.hpp" #line 12 "numeric/internal/two_pointer_technique.hpp" #line 15 "numeric/internal/two_pointer_technique.hpp" namespace uni { namespace internal { namespace interval_scanner_impl { template<class T> using interval = std::pair<T, T>; template<class T> using intervals = std::vector<std::pair<T, T>>; template<class T> struct base { protected: std::function<bool(T)> _validate; public: base(std::function<bool(T)> validate) : _validate(validate) {} void scan(T, T, T) { static_assert(internal::EXCEPTION_ON_TYPE<T>, "not implemented: scan()"); } void split(const T first, const T last, intervals<T> *intervals) const { std::valarray<bool> _valid(false, last - first); for(auto itr=first,index=0; itr!=last; ++itr, ++index) _valid[index] = _validate(itr); auto can_begin = [&](const T itr) { const auto index = itr - first; if(itr == first) return _valid[index]; if(itr == last) return false; if(not _valid[index-1] and _valid[index]) return true; return false; }; auto is_end = [&](const T itr) { const auto index = itr - first; if(itr == first) return false; if(itr == last) return _valid[index-1]; if(_valid[index-1] and not _valid[index]) return true; return false; }; { intervals->clear(); T start = first; for(auto itr=first; ; ++itr) { if(can_begin(itr)) start = itr; if(is_end(itr)) intervals->emplace_back(start, itr); if(itr == last) break; } } } void scan_all(const T first, const T last) const { intervals<T> targets; this->split(first, last, &targets); ITR(start, end, targets) this->scan(first, start, end); } }; } // namespace interval_scanner_impl } // namespace internal template<class T> struct exclusive_interval_scanner : internal::interval_scanner_impl::base<T> { private: std::function<void(T)> _init; std::function<bool(T)> _can_expand; std::function<void(T)> _expand, _contract; std::function<void(T, T)> _apply; public: using interval = internal::interval_scanner_impl::interval<T>; using intervals = internal::interval_scanner_impl::intervals<T>; exclusive_interval_scanner( std::function<bool(T)> validate, std::function<void(T)> init, std::function<bool(T)> can_expand, std::function<void(T)> expand, std::function<void(T)> contract, std::function<void(T, T)> apply ) : internal::interval_scanner_impl::base<T>(validate), _init(init), _can_expand(can_expand), _expand(expand), _contract(contract), _apply(apply) {} template<const bool FOLLOWING = true> void scan(const T start, const T end) const { T l_itr=start, r_itr=start; while(l_itr < end) { if (FOLLOWING and r_itr <= l_itr) { r_itr = l_itr+1; _init(l_itr); } while(r_itr < end && _can_expand(r_itr)) { _expand(r_itr++); } _apply(l_itr, r_itr); _contract(l_itr++); } }; template<const bool FOLLOWING = true> void scan_all(const T first, const T last) const { intervals targets; this->split(first, last, &targets); ITR(start, end, targets) this->scan<FOLLOWING>(start, end); } }; template<class T> struct inclusive_interval_scanner : internal::interval_scanner_impl::base<T> { protected: std::function<void()> _init; std::function<bool()> _valid; std::function<void(T)> _expand, _contract; std::function<void(T, T)> _apply; public: using interval = internal::interval_scanner_impl::interval<T>; using intervals = internal::interval_scanner_impl::intervals<T>; inclusive_interval_scanner( std::function<bool(T)> validate, std::function<void()> init, std::function<bool()> valid, std::function<void(T)> expand, std::function<void(T)> contract, std::function<void(T, T)> apply ) : internal::interval_scanner_impl::base<T>(validate), _init(init), _valid(valid), _expand(expand), _contract(contract), _apply(apply) {} template<const bool INVERSE = false, const bool FOLLOWING = true, const bool CONFIRMATION = true> void scan(const T start, const T end) const { T l_itr = start, r_itr = start; _init(); while(l_itr < end) { if(FOLLOWING and r_itr < l_itr) { r_itr = l_itr; _init(); } if(r_itr < end and (INVERSE ^ _valid())) { _expand(r_itr++); } else { _contract(l_itr++); } if(!CONFIRMATION or _valid()) _apply(l_itr, r_itr); } } template<const bool INVERSE = false, const bool FOLLOWING = true, const bool CONFIRMATION = true> void scan_all(const T first, const T last) const { intervals targets; this->split(first, last, &targets); ITR(start, end, targets) this->scan<INVERSE,FOLLOWING,CONFIRMATION>(start, end); } }; } // namespace uni #line 2 "numeric/internal/mo.hpp" #line 12 "numeric/internal/mo.hpp" #line 16 "numeric/internal/mo.hpp" #line 19 "numeric/internal/mo.hpp" #line 22 "numeric/internal/mo.hpp" #line 26 "numeric/internal/mo.hpp" namespace uni { template<class R, class EF, class PF, class EB = EF, class PB = PF> class interval_plannner { using size_type = internal::size_t; public: EF _expand_front; EB _expand_back; PF _contract_front; PB _contract_back; R _evaluate; using evaluator_result_t = std::invoke_result_t<R>; interval_plannner( EF expand_front, EB expand_back, PF contract_front, PB contract_back, R evaluate ) noexcept(NO_EXCEPT) : _expand_front(expand_front), _expand_back(expand_back), _contract_front(contract_front), _contract_back(contract_back), _evaluate(evaluate) {} interval_plannner(EF expand, PF contract, R evaluate) noexcept(NO_EXCEPT) : interval_plannner(expand, expand, contract, contract, evaluate) {} template< std::input_iterator QI, std::sentinel_for<QI> QS, std::output_iterator<evaluator_result_t> RI > void scan(const QI query_first, const QS query_last, const RI res_first) noexcept(NO_EXCEPT) { const auto q = std::ranges::distance(query_first, query_last); size_type n = 0; for(auto query=query_first; query!=query_last; ++query) { chmax(n, std::ranges::max(query->first, query->second)); } n = std::bit_ceil(uni::to_unsigned(n)); std::vector<i64> orders(q); { auto query = query_first; auto order = orders.begin(); for(; query!=query_last; ++query, ++order) { *order = hilbert_order<i64>(n, *query); } } std::vector<size_type> indices(q); std::iota(ALL(indices), 0); std::ranges::sort( indices, [&orders](const size_type i, const size_type j) { return orders[i] < orders[j]; } ); size_type l = 0, r = 0; ITR(i, indices) { while(l > query_first[i].first) _expand_front(--l); while(r < query_first[i].second) _expand_back(r++); while(l < query_first[i].first) _contract_front(l++); while(r > query_first[i].second) _contract_back(--r); res_first[i] = _evaluate(); } } template<std::input_iterator QI, std::sentinel_for<QI> QS> auto scan(const QI query_first, const QS query_last) noexcept(NO_EXCEPT) { valarray<evaluator_result_t> res(std::ranges::distance(query_first, query_last)); this->scan(query_first, query_last, std::ranges::begin(res)); return res; } template<std::ranges::input_range Q> auto scan(const Q& queries) noexcept(NO_EXCEPT) { valarray<evaluator_result_t> res(std::ranges::distance(queries)); this->scan(std::ranges::begin(queries), std::ranges::end(queries), std::ranges::begin(res)); return res; } }; } // namespace uni #line 2 "numeric/leveler.hpp" #line 7 "numeric/leveler.hpp" #line 10 "numeric/leveler.hpp" #line 13 "numeric/leveler.hpp" #line 15 "numeric/leveler.hpp" #line 18 "numeric/leveler.hpp" namespace uni { template<class T = internal::size_t> struct leveler { using value_type = T; using size_type = internal::size_t; private: uni::valarray<value_type> _bases; size_type _dim; value_type _max; inline value_type _compute_max() const noexcept(NO_EXCEPT) { return std::reduce(std::begin(this->_bases), std::end(this->_bases), 1, std::multiplies<value_type>{}); } public: leveler(const std::initializer_list<value_type> bases) noexcept(NO_EXCEPT) : _bases(bases), _dim(std::ranges::size(bases)) { this->_max = this->_compute_max(); } template<class I> leveler(I first, I last) noexcept(NO_EXCEPT) : _bases(first, last), _dim(std::ranges::distance(first, last)) { this->_max = this->_compute_max(); } template<std::ranges::forward_range R> leveler(R&& range) noexcept(NO_EXCEPT) : leveler(std::ranges::begin(range), std::ranges::end(range)) {} template<std::integral... Values> leveler(const Values... bases) noexcept(NO_EXCEPT) : leveler(std::initializer_list<value_type>{ bases... }) {} inline size_type dimension() const noexcept(NO_EXCEPT) { return this->_dim; } inline value_type sup() const noexcept(NO_EXCEPT) { return this->_max; } inline value_type convert(const std::initializer_list<value_type> inds) const noexcept(NO_EXCEPT) { return this->convert(inds | std::views::all); } template<std::ranges::forward_range R> inline value_type convert(R&& range) const noexcept(NO_EXCEPT) { assert(std::ranges::distance(range) == std::ranges::ssize(this->_bases)); value_type res = 0; { auto size = std::ranges::begin(this->_bases); ITR(v, range) { assert(0 <= v and v < *size); res *= *(size++); res += v; } } return res; } template<std::integral... Values> inline value_type convert(const Values... inds) const noexcept(NO_EXCEPT) { return this->convert({ inds... }); } inline uni::valarray<value_type> revert(value_type id) const noexcept(NO_EXCEPT) { assert(0 <= id and id < this->sup()); uni::valarray<value_type> res(std::size(this->_bases)); REPD(i, std::size(this->_bases)) { res[i] = id % this->_bases[i]; id /= this->_bases[i]; } return res; } auto _debug() const { return this->_bases; } }; } #line 2 "numeric/matrix.hpp" #line 6 "numeric/matrix.hpp" #line 9 "numeric/matrix.hpp" #line 12 "numeric/matrix.hpp" #line 14 "numeric/matrix.hpp" #line 16 "numeric/matrix.hpp" namespace uni { namespace internal { template<class Base> struct matrix_core : Base { using Base::Base; using value_type = typename Base::value_type; using size_type = typename Base::size_type; using vector_type = typename Base::row_type; static constexpr auto identity(const size_type n, const value_type& val = 1) noexcept(NO_EXCEPT) { matrix_core res(n); REP(i, n) res(i, i) = val; return res; } inline constexpr bool square() const noexcept(NO_EXCEPT) { return this->height() == this->width(); } constexpr auto& operator+=(const value_type& rhs) noexcept(NO_EXCEPT) { REP(i, this->height()) REP(j, this->width()) this->operator()(i, j) += rhs; return *this; } template<class... Ts> constexpr auto& operator+=(const matrix_core<Ts...>& rhs) noexcept(NO_EXCEPT) { REP(i, this->height()) REP(j, this->width()) this->operator()(i, j) += rhs(i, j); return *this; } template<weakly_addition_assignable<matrix_core> T> inline constexpr auto operator+(const T& rhs) const noexcept(NO_EXCEPT) { return matrix_core(*this) += rhs; } constexpr auto& operator-=(const value_type& rhs) noexcept(NO_EXCEPT) { REP(i, this->height()) REP(j, this->width()) this->operator()(i, j) -= rhs; return *this; } template<class... Ts> constexpr auto& operator-=(const matrix_core<Ts...>& rhs) noexcept(NO_EXCEPT) { REP(i, this->height()) REP(j, this->width()) this->operator()(i, j) -= rhs(i, j); return *this; } template<weakly_subtraction_assignable<matrix_core> T> inline constexpr auto operator-(const T& rhs) const noexcept(NO_EXCEPT) { return matrix_core(*this) -= rhs; } template<class... Ts> constexpr auto operator*(const matrix_core<Ts...>& rhs) const noexcept(NO_EXCEPT) { assert(this->width() == rhs.height()); matrix_core res(this->height(), rhs.width()); REP(i, this->height()) REP(j, rhs.width()) REP(k, this->width()) { res(i, j) += (*this)(i, k) * rhs(k, j); } return res; } template<std::ranges::input_range Vector> requires (!internal::derived_from_template<Vector, matrix_core>) && internal::weakly_multipliable<value_type, std::ranges::range_value_t<Vector>> constexpr auto operator*(const Vector& rhs) const noexcept(NO_EXCEPT) { debug(*this, rhs); assert(this->width() == std::ranges::ssize(rhs)); Vector res(this->height()); REP(i, this->height()) REP(j, this->width()) res[i] += this->operator()(i, j) * rhs[j]; return res; } template<std::ranges::input_range Vector> requires (!internal::derived_from_template<Vector, matrix_core>) && internal::weakly_multipliable<std::ranges::range_value_t<Vector>, value_type> friend constexpr auto operator*(const Vector& lhs, const matrix_core& rhs) noexcept(NO_EXCEPT) { debug(lhs, rhs); assert(std::ranges::ssize(lhs) == rhs.height()); Vector res(rhs.width()); REP(i, rhs.height()) REP(j, rhs.width()) res[j] += lhs[j] * rhs[i][j]; return res; } constexpr auto operator*(const value_type& rhs) noexcept(NO_EXCEPT) { auto res = *this; REP(i, res.height()) REP(j, res.width()) res(i, j) *= rhs; return res; } template<multipliable<matrix_core> T> constexpr auto& operator*=(const T& rhs) noexcept(NO_EXCEPT) { matrix_core res = *this * rhs; this->assign(res); return *this; } constexpr auto& operator/=(const value_type& rhs) noexcept(NO_EXCEPT) { REP(i, this->height()) REP(j, this->width()) this->operator()(i, j) /= rhs; return *this; } inline constexpr auto operator/(const value_type& rhs) const noexcept(NO_EXCEPT) { return matrix_core(*this) /= rhs; } constexpr auto& operator%=(const value_type& rhs) noexcept(NO_EXCEPT) { REP(i, this->height()) REP(j, this->width()) this->operator()(i, j) %= rhs; return *this; } inline constexpr auto operator%(const value_type& rhs) const noexcept(NO_EXCEPT) { return matrix_core(*this) %= rhs; } template<std::integral K> constexpr auto pow(const K n) const noexcept(NO_EXCEPT) { assert(this->height() == this->width()); if constexpr(std::signed_integral<K>) assert(n >= 0); return uni::pow(*this, n, {}, matrix_core::identity(this->height())); } constexpr auto find_pivot(const size_type rank, const size_type col) const noexcept(NO_EXCEPT) { size_type pivot = -1; REP(i, rank, this->height()) { if(this->operator()(i, col) != 0) { pivot = i; break; } } return pivot; } template<bool DIAGONALIZE = false> constexpr void sweep(const size_type rank, const size_type col, const size_type pivot) noexcept(NO_EXCEPT) requires modint_family<value_type> { std::swap(this->operator[](pivot), this->operator[](rank)); if constexpr(DIAGONALIZE) { const auto inv = this->operator()(rank, col).inv(); REP(j, this->width()) this->operator()(rank, j) *= inv; } REP(i, (DIAGONALIZE ? 0 : rank + 1), this->height()) { if(i != rank && this->operator()(i, col) != 0) { const auto fac = this->operator()(i, col); REP(j, this->width()) this->operator()(i, j) -= this->operator()(rank, j) * fac; } } } template<size_type IGNORE_WIDTH = 0, bool DIAGONALIZE = false> inline constexpr auto transform_to_upper_triangular() noexcept(NO_EXCEPT) requires modint_family<value_type> { size_type rank = 0; REP(j, this->width() - IGNORE_WIDTH) { const auto pivot = this->find_pivot(rank, j); if(pivot == -1) continue; this->template sweep<DIAGONALIZE>(rank++, j, pivot); } return rank; } template<size_type IGNORE_WIDTH> inline constexpr auto transform_to_lower_triangular() noexcept(NO_EXCEPT) requires modint_family<value_type> { const auto rank = this->template transform_to_upper_triangular<IGNORE_WIDTH>(); this->transpose(); return rank; } template<std::ranges::input_range Vector, class Sol = void, class System = void> constexpr std::optional<size_type> solve_linear_equation( const Vector& v, Sol *const sol = nullptr, System *const system = nullptr ) const noexcept(NO_EXCEPT) requires modint_family<value_type> { static_assert(!(std::same_as<Sol, void>) || (std::same_as<System, void>)); assert(this->height() == std::ranges::ssize(v)); matrix_core mat(this->height(), this->width() + 1); REP(i, this->height()) { REP(j, this->width()) mat(i, j) = this->operator()(i, j); mat(i, this->width()) = v[i]; } const auto rank = mat.transform_to_upper_triangular<1, true>(); REP(i, rank, this->height()) if(mat(i, this->width()) != value_type::zero) return {}; if constexpr(!std::same_as<Sol, void>) { static_assert(std::ranges::output_range<Sol, value_type>); static_assert(std::ranges::output_range<std::ranges::range_value_t<System>, value_type>); assert(!sol || system); if(sol) { sol->assign(this->width(), value_type::zero); std::vector<size_type> pivots(system ? this->width() : 0, -1); for(size_type i = 0, j = 0; i < rank; ++i) { while(mat(i, j) == value_type::zero) ++j; sol->operator[](j) = mat(i, this->width()); if constexpr(!std::same_as<System, void>) if(system) { pivots[j] = i; } } if constexpr(!std::same_as<System, void>) if(system) { REP(j, this->width()) { if(pivots[j] != -1) continue; typename System::vector_type x(this->width()); x[j] = value_type::one; REP(k, j) if(pivots[k] != -1) x[k] = -mat(pivots[k], j); system->push_back(x); } system->resize(system->size(), this->width()); } } } return rank; } value_type determinant() const noexcept(NO_EXCEPT) requires modint_family<value_type> { assert(this->square()); auto mat = *this; value_type det = value_type::one; REP(j, this->height()) { const auto pivot = mat.find_pivot(j, j); if(j < pivot) std::swap(mat[pivot], mat[j]), det = -det; if(mat(j, j) == 0) return 0; REP(i, j + 1, this->height()) { while(mat(i, j) != 0) { const auto c = static_cast<value_type>(-to_signed(mat(j, j).val() / mat(i, j).val())); REP(k, j, this->height()) mat(j, k) += mat(i, k) * c; std::swap(mat[i], mat[j]), det = -det; } } } REP(i, mat.height()) det *= mat(i, i); return det; } }; } // namespace internal template<class T, class Base = grid<T>> using matrix = internal::matrix_core<Base>; template<class T> using valmatrix = internal::matrix_core<valgrid<T>>; template<class T> using unfolded_matrix = internal::matrix_core<unfolded_grid<T>>; template<class T> using unfolded_valmatrix = internal::matrix_core<unfolded_valgrid<T>>; } // namespace uni #line 2 "numeric/numerical_sequence.hpp" #line 6 "numeric/numerical_sequence.hpp" #line 8 "numeric/numerical_sequence.hpp" namespace uni { namespace numerical_sequence { namespace internal { using size_t = std::int64_t; template<class T> struct single_constant { using value_type = T; private: value_type _val; public: constexpr single_constant() = default; constexpr single_constant(const value_type& val) noexcept(NO_EXCEPT) : _val(val) {} inline constexpr const value_type& val() const noexcept(NO_EXCEPT) { return this->_val; } inline constexpr operator value_type() const noexcept(NO_EXCEPT) { return this->_val; } }; } // namespace internl template<class T> struct term { using size_type = internal::size_t; using value_type = T; private: size_type _index; value_type _val; public: constexpr term() = default; constexpr explicit term(const size_type index, const value_type& val) noexcept(NO_EXCEPT) : _index(index), _val(val) {} inline constexpr size_type index() const noexcept(NO_EXCEPT) { return this->_index; } inline constexpr const value_type& val() const noexcept(NO_EXCEPT) { return this->_val; } }; template<class T, internal::size_t INDEX> struct static_term : internal::single_constant<T> { using internal::single_constant<T>::single_constant; using size_type = internal::size_t; using value_type = T; inline constexpr size_type index() const noexcept(NO_EXCEPT) { return INDEX; } inline constexpr operator term<value_type>() const noexcept(NO_EXCEPT) { return term(INDEX, this->_val); } }; template<class T> struct common_difference : internal::single_constant<T> { using internal::single_constant<T>::single_constant; }; template<class T> struct common_ratio : internal::single_constant<T> { using internal::single_constant<T>::single_constant; }; template<class T> struct arithmetic { using size_type = internal::size_t; using value_type = T; protected: value_type _begin, _diff; public: constexpr arithmetic() = default; constexpr arithmetic(const static_term<value_type,0>& begin, const common_difference<value_type>& diff) : _begin(static_cast<value_type>(begin.val())), _diff(diff.val()) {} constexpr arithmetic(const common_difference<value_type>& diff, const static_term<value_type,0>& begin) : arithmetic(begin, diff) {} constexpr arithmetic(const term<value_type>& p, const common_difference<value_type>& diff) noexcept(NO_EXCEPT) : arithmetic(diff, static_cast<value_type>(p.val() - diff * p.index())) {} constexpr arithmetic(const common_difference<value_type>& diff, const term<value_type>& p) noexcept(NO_EXCEPT) : arithmetic(p, diff) {} constexpr arithmetic(const term<value_type> p, const term<value_type> q) noexcept(NO_EXCEPT) : arithmetic(p, common_difference(static_cast<value_type>((p.val() - q.val()) / (p.index() - q.index())))) {} inline constexpr term<value_type> operator[](const size_type k) const noexcept(NO_EXCEPT) { return term(k, static_cast<value_type>(this->_begin + this->_diff * k)); } inline constexpr value_type sum(const size_type k) const noexcept(NO_EXCEPT) { return static_cast<value_type>((this->_begin * k) + (k - 1) * k / 2 * this->_diff); } inline constexpr value_type sum(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return this->sum(r) - this->sum(l); } }; template<class T> struct geometric { using size_type = internal::size_t; using value_type = T; protected: value_type _begin, _ratio; public: constexpr geometric() = default; constexpr geometric(const static_term<value_type,0> begin, const common_ratio<T> ratio) noexcept(NO_EXCEPT) : _begin(begin), _ratio(ratio) {}; inline constexpr term<value_type> operator[](const size_type k) const noexcept(NO_EXCEPT) { return term(k, this->_begin * uni::pow(this->_diff, k)); } inline constexpr value_type sum(const size_type k) const noexcept(NO_EXCEPT) { if(this->_ratio == 1) return this->_begin * this->k; else { return this->_begin * (uni::pow(this->_ratio, k) - 1) / (this->_ratio - 1); } return ; } inline constexpr value_type sum(const size_type l, const size_type r) const noexcept(NO_EXCEPT) { return this->sum(r) - this->sum(l); } }; } // namespace numerical_sequence } // namespace uni #line 2 "numeric/prime_counter.hpp" #line 6 "numeric/prime_counter.hpp" #line 10 "numeric/prime_counter.hpp" #line 12 "numeric/prime_counter.hpp" #line 14 "numeric/prime_counter.hpp" namespace uni { static inline i64 float_div(const i64 n, const i64 p) { return static_cast<i64>(static_cast<double>(n) / static_cast<double>(p)); }; // Thanks to: https://nyaannyaan.github.io/library/multiplicative-function/prime-counting-faster.hpp __attribute__((target("avx2"), optimize("O3", "unroll-loops"))) i64 count_primes(const u64 n) noexcept(NO_EXCEPT) { if(n == 0 || n == 1) return 0; const i64 sqrt_n = uni::sqrt_floor(n); const i64 m = float_div(n, sqrt_n); std::vector<i64> hl(m); REP(i, 1, m) hl[i] = float_div(n, i) - 1; std::vector<i32> hs(sqrt_n + 1); std::iota(ALL(hs), -1); for(i32 x=2, pi=0; x <= sqrt_n; ++x) { if(hs[x] == hs[x - 1]) continue; const i64 x2 = static_cast<i64>(x) * x; const i64 imax = std::min(m, float_div(n, x2) + 1); i64 ix = x; REP(i, 1, imax) { hl[i] -= (ix < m ? hl[ix] : hs[float_div(n, ix)]) - pi; ix += x; } FORD(k, x2, sqrt_n) hs[k] -= hs[float_div(k, x)] - pi; ++pi; } return hl[1]; } inline i64 count_primes(const i64 l, const i64 r) noexcept(NO_EXCEPT) { assert(l <= r); return count_primes(r) - count_primes(l - 1); } } // namespace uni #line 2 "numeric/prime_sieve.hpp" #line 5 "numeric/prime_sieve.hpp" #line 8 "numeric/prime_sieve.hpp" #line 11 "numeric/prime_sieve.hpp" #line 14 "numeric/prime_sieve.hpp" namespace uni { template<class container = valarray<bool>> struct prime_flags : container { prime_flags(const internal::size_t max) noexcept(NO_EXCEPT) : container(max+1, true) { (*this)[0] = (*this)[1] = false; for(internal::size_t p=2; p*p<=max; p++) if((*this)[p]) { for(internal::size_t i=p*p; i<=max; i+=p) (*this)[i] = false; } } }; template<class T, class container = vector<T>> struct prime_sieve : container { protected: std::vector<bool> is_prime; public: prime_sieve() noexcept(NO_EXCEPT) {} prime_sieve(const T max) noexcept(NO_EXCEPT) : is_prime(max+1, true) { is_prime[0] = is_prime[1] = false; FOR(p, T{2}, max) { if(is_prime[p]) { for(T i = mul_overflow(p,p).value_or(max+1); i<=max; i+=p) is_prime[i] = false; this->emplace_back(p); } } } inline bool operator()(const T index) const noexcept(NO_EXCEPT) { return is_prime[index]; } }; } // namespace uni #line 2 "numeric/quotient_enumerator.hpp" #line 6 "numeric/quotient_enumerator.hpp" #line 10 "numeric/quotient_enumerator.hpp" #line 12 "numeric/quotient_enumerator.hpp" namespace uni { template<class T, bool CEIL = false> struct quotient_enumerator { using value_type = std::tuple<T,T,T>; // (q, l, r) using size_type = T; private: T _n = 0, _n_impl = 0; size_type _size = -1; protected: using iterator_interface = internal::bidirectional_iterator_interface<const value_type>; public: // Enumerate tuple of (q, l, r), which means (floor/ceil)(_n/k) == q (l <= k <= r). quotient_enumerator(const T n) noexcept(NO_EXCEPT) : _n(n), _n_impl(n - CEIL) { assert(n > 0); } struct iterator; using const_iterator = iterator; inline auto begin() noexcept(NO_EXCEPT) { return iterator(this->_n_impl, 1); } inline auto end() noexcept(NO_EXCEPT) { return iterator(this->_n_impl, this->_n + 1); } inline auto rbegin() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } inline auto size() noexcept(NO_EXCEPT) { if(this->_size < 0) { size_type r = uni::sqrt_floor(this->_n_impl); this->_size = 2 * r - (this->_n_impl < r * (r + 1)) + CEIL; } return this->_size; } struct iterator : virtual iterator_interface { using value_type = quotient_enumerator::value_type; using reference = value_type; protected: T _n_impl = 0; T _q = 0, _l = 0, _r = 0; void _set_l(const T l) noexcept(NO_EXCEPT) { this->_l = l, this->_q = this->_n_impl / l; if(this->_q == 0) { if(CEIL) { if(l == this->_n_impl + 1) this->_r = l; } return; } this->_r = this->_n_impl / this->_q; } void _set_r(const T r) noexcept(NO_EXCEPT) { this->_r = r, this->_q = this->_n_impl / r; this->_l = this->_n_impl / (this->_q + 1) + 1; } public: iterator() noexcept = default; iterator(const T n, const T l) noexcept(NO_EXCEPT) : _n_impl(n) { this->_set_l(l); } friend inline bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) { return lhs._l == rhs._l; } inline value_type operator*() const noexcept(NO_EXCEPT) { return { this->_q + CEIL, this->_l, this->_r }; } inline auto& operator++() noexcept(NO_EXCEPT) { this->_set_l(this->_r + 1); return *this; } inline auto& operator--() noexcept(NO_EXCEPT) { this->_set_r(this->_l - 1); return *this; } inline auto operator++(int) noexcept(NO_EXCEPT) { const auto res = *this; this->_set_l(this->_r + 1); return res; } inline auto operator--(int) noexcept(NO_EXCEPT) { const auto res = *this; this->_set_r(this->_l - 1); return res; } }; }; } // namespace uni namespace std::ranges { template<class T> inline constexpr bool enable_borrowed_range<uni::quotient_enumerator<T>> = true; } // namespace std::ranges #line 2 "numeric/repeater.hpp" #line 7 "numeric/repeater.hpp" #line 11 "numeric/repeater.hpp" #line 13 "numeric/repeater.hpp" namespace uni { template<class T, internal::size_t SUP, internal::size_t DEFAULT_DEPTH = 64> struct repeater { using value_type = T; using size_type = internal::size_t; private: std::vector<std::array<T, SUP>> _app; inline void _extend(const std::size_t k) noexcept(NO_EXCEPT) { const auto size = this->_app.size(); const auto w = to_unsigned(std::bit_width(k)); if(w <= size) return; this->_app.resize(w); REP(d, size, w) { REP(n, SUP) { this->_app[d][n] = this->_app[d - 1][this->_app[d - 1][n]]; } } } template<std::unsigned_integral K> struct applyer { private: K _k; repeater* _super; public: applyer(const K k, repeater *const super) noexcept(NO_EXCEPT) : _k(k), _super(super) {} inline K times() const noexcept(NO_EXCEPT) { return this->_k; } inline value_type operator()(value_type val) const noexcept(NO_EXCEPT) { REP(d, this->_super->_app.size()) { if(uni::bit(this->_k, d)) val = this->_super->_app[d][val]; } return val; } }; public: template<class F> requires std::convertible_to<std::invoke_result_t<F, T>, T> explicit repeater(F&& f) noexcept(NO_EXCEPT) : _app(1) { this->_app.reserve(DEFAULT_DEPTH); REP(n, SUP) this->_app[0][n] = static_cast<value_type>(f(n)); }; template<std::ranges::sized_range R> explicit repeater(R&& f) noexcept(NO_EXCEPT) : _app(1) { assert(std::ranges::size(f) <= SUP); this->_app.reserve(DEFAULT_DEPTH); std::ranges::copy(f, std::ranges::begin(this->_app[0])); }; template<std::integral K> inline auto operator[](K k) noexcept(NO_EXCEPT) { if(std::signed_integral<K>) assert(0 <= k); this->_extend(static_cast<std::size_t>(k)); return applyer{ to_unsigned(k), this }; } }; } // namespace uni #line 2 "numeric/stern_brocot_tree.hpp" #line 6 "numeric/stern_brocot_tree.hpp" #line 8 "numeric/stern_brocot_tree.hpp" #line 10 "numeric/stern_brocot_tree.hpp" #line 12 "numeric/stern_brocot_tree.hpp" namespace uni { // Thanks to: https://maspypy.github.io/library/nt/stern_brocot_tree.hpp template< class Value = i32, class Middle = i64, class Large = i128, class Fraction = spair<Value>, std::ranges::range Path = uni::vector<Value> > struct stern_brocot_tree { using value_type = Value; using middle_type = Middle; using large_type = middle_type; using path_type = Path; using fraction_type = Fraction; static constexpr std::tuple<path_type, fraction_type, fraction_type> path_and_rang(const fraction_type x) { path_type path; fraction_type l = { 0, 1 }, r = { 1, 0 }; fraction_type m = { 1, 1 }; middle_type det_l = l.first * x.second - l.second * x.first; middle_type det_r = r.first * x.second - r.second * x.first; middle_type det_m = det_l + det_r; while(true) { if(det_m == 0) break; middle_type k = uni::div_ceil(-det_m, det_r); path.emplace_back(k); l = { l.first + k * r.first, l.second + k * r.second }; m = { l.first + r.first, l.second + r.second }; det_l += k * det_r; det_m += k * det_r; if(det_m == 0) break; k = uni::div_ceil(det_m, -det_l); path.emplace_back(k); r = { r.first + k * l.first, r.second + k * l.second }; m = { l.first + r.first, l.second + r.second }; det_r += k * det_l; det_m += k * det_l; } return { path, l, r }; } static constexpr path_type path(const fraction_type x) { const auto [ path, l, r ] = path_and_rang(x); return path; } static constexpr spair<fraction_type> range(const fraction_type x) { const auto [ path, l, r ] = path_and_rang(x); return { l, r }; } // x in range(y) static constexpr bool in_subtree(const fraction_type x, const fraction_type y) { const auto [ l, r ] = range(y); const bool ok_l = static_cast<middle_type>(x.first) * l.second - static_cast<middle_type>(x.second) * l.first > 0; const bool ok_r = static_cast<middle_type>(r.first) * x.second - static_cast<middle_type>(r.second) * x.first > 0; return ok_l && ok_r; } template<class T = middle_type, class Frac = spair<middle_type>> static constexpr Frac from_path(const path_type &p) { Frac l = { 0, 1 }, r = { 1, 0 }; FOR(i, std::ranges::size(p)) { middle_type k = p[i]; if((i & 1) == 0) { l.first += static_cast<T>(k) * r.first; l.second += static_cast<T>(k) * r.second; } if((i & 1) == 1) { r.first += static_cast<T>(k) * l.first; r.second += static_cast<T>(k) * l.second; } } return { l.first + r.first, l.second + r.second }; } static constexpr spair<fraction_type> children(const fraction_type x) { const auto [ l, r ] = range(x); const fraction_type lc = { l.first + x.first, l.second + x.second }; const fraction_type rc = { x.first + r.first, x.second + r.second }; return { lc, rc }; } static constexpr fraction_type lowest_common_ancestor(const fraction_type x, const fraction_type y) { const auto px = path(x); const auto py = path(y); path_type path; FOR(i, uni::min(std::ranges::ssize(px), std::ranges::ssize(py))) { middle_type k = uni::min(px[i], py[i]); path.emplace_back(k); if(k < px[i] || k < py[i]) break; } return from_path(path); } static constexpr fraction_type ancestor(const fraction_type x, middle_type dep) { fraction_type l = { 0, 1 }, r = { 1, 0 }; fraction_type m = { 1, 1 }; middle_type det_l = l.first * x.second - l.second * x.first; middle_type det_r = r.first * x.second - r.second * x.first; middle_type det_m = det_l + det_r; while(true) { if(det_m == 0 || dep == 0) break; middle_type k = uni::min(dep, uni::div_ceil(-det_m, det_r)); l = { l.first + k * r.first, l.second + k * r.second }; m = { l.first + r.first, l.second + r.second }; det_l += k * det_r; det_m += k * det_r; dep -= k; if(det_m == 0 || dep == 0) break; k = uni::min(dep, uni::div_ceil(det_m, -det_l)); r = {r.first + k * l.first, r.second + k * l.second }; m = { l.first + r.first, l.second + r.second }; det_r += k * det_l; det_m += k * det_l; dep -= k; } if(dep == 0) return m; return { -1, -1 }; } static constexpr std::string to_string(const path_type &p) { std::string res; char c = 'L'; ITR(x, p) { c = 'L' + 'R' - c; if(x == 0) continue; res += c; res += " " + std::to_string(x); } return res; } }; } // namespace uni #line 2 "numeric/subset_enumerator.hpp" #line 6 "numeric/subset_enumerator.hpp" #line 10 "numeric/subset_enumerator.hpp" #line 13 "numeric/subset_enumerator.hpp" namespace uni { template<std::unsigned_integral T> struct subset_enumerator { using value_type = T; using size_type = internal::size_t; private: T _n = 0; protected: using iterator_interface = internal::bidirectional_iterator_interface<const value_type>; public: // Enumerate tuple of (q, l, r), which means (floor/ceil)(_n/k) == q (l <= k <= r). subset_enumerator(const T n) noexcept(NO_EXCEPT) : _n(n) { assert(n >= 0); } struct iterator; using const_iterator = iterator; inline auto begin() noexcept(NO_EXCEPT) { return iterator(this->_n, this->_n); } inline auto end() noexcept(NO_EXCEPT) { return iterator(this->_n, 0, true); } inline auto rbegin() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->end()); } inline auto rend() noexcept(NO_EXCEPT) { return std::make_reverse_iterator(this->begin()); } inline auto size() noexcept(NO_EXCEPT) { return static_cast<size_type>(1) << std::popcount(this->_n); } struct iterator : iterator_interface { protected: value_type _n = 0, _v = 0; bool _end = false; public: iterator() noexcept = default; iterator(const T n, const T v, const bool end = false) noexcept(NO_EXCEPT) : _n(n), _v(v), _end(end) {}; friend inline bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) { if(rhs._end) return lhs._end; if(lhs._end) return false; return lhs._v == rhs._v; }; friend inline auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) { if(rhs._end) { if(lhs._end) return std::partial_ordering::equivalent; return std::partial_ordering::less; } if(lhs._end) { return std::partial_ordering::greater; } return comapre_as_bitset(rhs._v, lhs._v); }; inline auto operator*() const noexcept(NO_EXCEPT) { return this->_v; } inline auto& operator++() noexcept(NO_EXCEPT) { if(this->_v == 0) { this->_end = true; } else { this->_v = (this->_v - 1) & this->_n; } return *this; } inline auto& operator--() noexcept(NO_EXCEPT) { if(this->_end) { this->_end = false; } else { const auto lsb = lowest_bit_pos(this->_n & ~this->_v); this->_v = ((this->_v >> lsb) | 1) << lsb; } return *this; } inline auto operator++(int) noexcept(NO_EXCEPT) { auto res = *this; ++res; return res; } inline auto operator--(int) noexcept(NO_EXCEPT) { auto res = *this; --res; return res; } }; }; } // namespace uni namespace std::ranges { template<class T> inline constexpr bool enable_borrowed_range<uni::subset_enumerator<T>> = true; } // namespace std::ranges #line 2 "numeric/subset_superset_transform.hpp" #line 6 "numeric/subset_superset_transform.hpp" #line 8 "numeric/subset_superset_transform.hpp" namespace uni { namespace superset_transform { template<std::ranges::random_access_range R, std::unsigned_integral Bit = std::uint32_t> void zeta(R& range) { const auto n = std::ranges::size(range); assert(std::has_single_bit(n)); for(Bit i = 1; i < n; i <<= 1) { for(Bit j = 0; j < n; ++j) { if((j & i) == 0) { range[j] += range[j | i]; } } } } template<std::ranges::random_access_range R, std::unsigned_integral Bit = std::uint32_t> void mobius(R& range) { const auto n = std::ranges::size(range); assert(std::has_single_bit(n)); for(Bit i = 1; i < n; i <<= 1) { for(Bit j = 0; j < n; ++j) { if((j & i) == 0) { range[j] -= range[j | i]; } } } } } // namespace superset_transform namespace subset_transform { template<std::ranges::random_access_range R, std::unsigned_integral Bit = std::uint32_t> void zeta(R& range) { const auto n = std::ranges::size(range); assert(std::has_single_bit(n)); for(Bit i = 1; i < n; i <<= 1) { for(Bit j = 0; j < n; ++j) { if((j & i) == 0) { range[j | i] += range[j]; } } } } template<std::ranges::random_access_range R, std::unsigned_integral Bit = std::uint32_t> void mobius(R& range) { const auto n = std::ranges::size(range); assert(std::has_single_bit(n)); for(Bit i = 1; i < n; i <<= 1) { for(Bit j = 0; j < n; ++j) { if((j & i) == 0) { range[j | i] -= range[j]; } } } } } // namespace subset_transform } // namespace uni #line 2 "include/snippets.hpp" #line 2 "snippet/fast_io.hpp" #line 5 "snippet/fast_io.hpp" #line 7 "snippet/fast_io.hpp" #ifdef __GNUC__ __attribute__((constructor)) inline void fast_io() noexcept(NO_EXCEPT) { std::ios::sync_with_stdio(false), std::cin.tie(nullptr); } #else inline void fast_io() noexcept(NO_EXCEPT) { std::ios::sync_with_stdio(false), std::cin.tie(nullptr); } #endif #line 2 "include/views.hpp" #line 2 "view/repeat.hpp" #line 8 "view/repeat.hpp" #line 12 "view/repeat.hpp" #line 2 "view/internal/box.hpp" #line 6 "view/internal/box.hpp" #line 9 "view/internal/box.hpp" namespace uni { namespace internal { #if CPP23 template<class T> concept boxable = std::copy_constructible<T> && std::is_object_v<T>; #else template<class T> concept boxable = std::copy_constructible<T> && std::is_object_v<T>; #endif template<boxable T> struct box : std::optional<T> { using std::optional<T>::optional; constexpr box() noexcept(std::is_nothrow_default_constructible_v<T>) requires std::default_initializable<T> : std::optional<T> { std::in_place } {} box(const box&) = default; box(box&&) = default; using std::optional<T>::operator=; constexpr box& operator=(const box& other) noexcept( std::is_nothrow_copy_constructible_v<T>) requires(!std::copyable<T>) && std::copy_constructible<T> { if(this != std::addressof(other)) { if((bool)other) this->emplace(*other); else this->reset(); } return *this; } constexpr box& operator=(box&& other) noexcept(std::is_nothrow_move_constructible_v<T>) requires(!std::movable<T>) { if(this != std::addressof(other)) { if((bool)other) this->emplace(std::move(*other)); else this->reset(); } return *this; } }; template<class T> concept boxable_copyable = std::copy_constructible<T> && ( std::copyable<T> || (std::is_nothrow_move_constructible_v<T> && std::is_nothrow_copy_constructible_v<T>) ); template<class T> concept boxable_movable = (!std::copy_constructible<T>) && (std::movable<T> || std::is_nothrow_move_constructible_v<T>); template<boxable T> requires boxable_copyable<T> || boxable_movable<T> struct box<T> { private: [[no_unique_address]] T _value = T(); public: box() requires std::default_initializable<T> = default; constexpr explicit box(const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>) requires std::copy_constructible<T> : _value(value) {} constexpr explicit box(T&& value) noexcept(std::is_nothrow_move_constructible_v<T>) : _value(std::move(value)) {} template<class... Args> requires std::constructible_from<T, Args...> constexpr explicit box(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>) : _value(std::forward<Args>(args)...) {} box(const box& ) = default; box(box&& ) = default; box& operator=(const box& ) requires std::copyable<T> = default; box& operator=(box&& ) requires std::movable<T> = default; constexpr box& operator=(const box& other) noexcept requires(!std::copyable<T>) && std::copy_constructible<T> { static_assert(std::is_nothrow_copy_constructible_v<T>); if(this != std::addressof(other)) { this->_value.~T(); std::construct_at(std::addressof(this->_value), *other); } return *this; } constexpr box& operator=(box&& other) noexcept requires(!std::movable<T>) { static_assert(std::is_nothrow_move_constructible_v<T>); if(this != std::addressof(other)) { this->_value.~T(); std::construct_at(std::addressof(this->_value), std::move(*other)); } return *this; } constexpr bool has_value() const noexcept { return true; }; constexpr T& operator*() noexcept { return this->_value; } constexpr const T& operator*() const noexcept { return this->_value; } constexpr T* operator->() noexcept { return std::addressof(this->_value); } constexpr const T* operator->() const noexcept { return std::addressof(this->_value); } }; } // namespace internal } // namespace uni #line 15 "view/repeat.hpp" #line 18 "view/repeat.hpp" namespace uni { template <std::move_constructible T, std::semiregular Bound = std::unreachable_sentinel_t> requires std::is_object_v<T> && std::same_as<T, std::remove_cv_t<T>> && ( std::is_integral_v<Bound> || std::same_as<Bound, std::unreachable_sentinel_t> ) struct repeat_view : public std::ranges::view_interface<repeat_view<T, Bound>> { private: internal::box<T> _value; [[no_unique_address]] Bound _bound = Bound(); struct iterator; template <typename Range> friend constexpr auto take_of_repeat_view(Range&&, std::ranges::range_difference_t<Range>); template <typename Range> friend constexpr auto drop_of_repeat_view(Range &&, std::ranges::range_difference_t<Range>); public: repeat_view() requires std::default_initializable<T> = default; constexpr explicit repeat_view(const T& val, Bound bound = Bound()) requires std::copy_constructible<T> : _value(val), _bound(bound) { if constexpr(!std::same_as<Bound, std::unreachable_sentinel_t>) assert(bound >= 0); } constexpr explicit repeat_view(T&& val, Bound bound = Bound()) : _value(std::move(val)), _bound(bound) {} template <typename... Args, typename... BoundArgs> requires std::constructible_from<T, Args...> && std::constructible_from<Bound, BoundArgs...> constexpr explicit repeat_view( std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<BoundArgs...> bound_args = std::tuple<>{} ) : _value(std::make_from_tuple<T>(std::move(args))), _bound(std::make_from_tuple<Bound>(std::move(bound_args))) {} constexpr iterator begin() const { return iterator(std::addressof(*this->_value)); } constexpr iterator end() const requires(!std::same_as<Bound, std::unreachable_sentinel_t>) { return iterator(std::addressof(*this->_value), this->_bound); } constexpr std::unreachable_sentinel_t end() const noexcept { return std::unreachable_sentinel; } constexpr auto size() const requires(!std::same_as<Bound, std::unreachable_sentinel_t>) { return to_unsigned(this->_bound); } }; template <typename T, typename Bound> repeat_view(T, Bound) -> repeat_view<T, Bound>; template <std::move_constructible T, std::semiregular Bound> requires std::is_object_v<T> && std::same_as<T, std::remove_cv_t<T>> && (std::is_integral_v<Bound> || std::same_as<Bound, std::unreachable_sentinel_t>) struct repeat_view<T, Bound>::iterator { private: using index_type = std::conditional_t<std::same_as<Bound, std::unreachable_sentinel_t>, std::ptrdiff_t, Bound>; const T* _value = nullptr; index_type _crrent = index_type(); constexpr explicit iterator(const T* val, index_type bound = index_type()) : _value(val), _crrent(bound) { if constexpr(!std::same_as<Bound, std::unreachable_sentinel_t>) assert(bound >= 0); } friend repeat_view; public: using iterator_concept = std::random_access_iterator_tag; using iterator_category = std::random_access_iterator_tag; using value_type = T; using difference_type = std::conditional_t< std::is_integral_v<index_type>, index_type, internal::iota_diff_t<index_type> >; iterator() = default; constexpr const T& operator*() const noexcept { return *this->_value; } constexpr iterator& operator++() { ++this->_crrent; return *this; } constexpr iterator operator++(int) { auto _tmp = *this; ++*this; return _tmp; } constexpr iterator& operator--() { if constexpr(!std::same_as<Bound, std::unreachable_sentinel_t>) assert(this->_crrent > 0); --this->_crrent; return *this; } constexpr iterator operator--(int) { auto _tmp = *this; --*this; return _tmp; } constexpr iterator& operator+=(difference_type diff) { if constexpr(!std::same_as<Bound, std::unreachable_sentinel_t>) assert(this->_crrent + diff >= 0); this->_crrent += diff; return *this; } constexpr iterator& operator-=(difference_type diff) { if constexpr(!std::same_as<Bound, std::unreachable_sentinel_t>) assert(this->_crrent - diff >= 0); this->_crrent -= diff; return *this; } constexpr const T& operator[](difference_type diff) const noexcept { return *(*this + diff); } friend constexpr bool operator==(const iterator& lhs, const iterator& rhs) { return lhs._crrent == rhs._crrent; } friend constexpr auto operator<=>(const iterator& lhs, const iterator& rhs) { return lhs._crrent <=> rhs._crrent; } friend constexpr iterator operator+(iterator itr, difference_type diff) { return itr += diff; } friend constexpr iterator operator+(difference_type diff, iterator itr) { return itr + diff; } friend constexpr iterator operator-(iterator itr, difference_type diff) { return itr -= diff; } friend constexpr difference_type operator-(const iterator& lhs, const iterator& rhs) { return ( static_cast<difference_type>(lhs._crrent) - static_cast<difference_type>(rhs._crrent) ); } }; namespace views { namespace internal { template<typename _Range> inline constexpr bool is_repeat_view = false; template <class T, class Bound> inline constexpr bool is_repeat_view<repeat_view<T, Bound>> = true; template <class T> concept can_repeat_view = requires { repeat_view(std::declval<T>()); }; template <class T, class Bound> concept can_bounded_repeat_view = requires { repeat_view(std::declval<T>(), std::declval<Bound>()); }; } // namespace internal struct Repeat { template <class T> requires internal::can_repeat_view<T> constexpr auto operator() [[nodiscard]] (T&& val) const { return repeat_view(std::forward<T>(val)); } template <class T, class Bound> requires internal::can_bounded_repeat_view<T, Bound> constexpr auto operator() [[nodiscard]] (T&& val, Bound bound) const { return repeat_view(std::forward<T>(val), bound); } }; inline constexpr Repeat repeat; namespace internal { template<class Range> constexpr auto take_of_repeat_view(Range&& range, std::ranges::range_difference_t<Range> diff) { using T = std::remove_cvref_t<Range>; static_assert(is_repeat_view<T>); if constexpr(std::ranges::sized_range<T>) return views::repeat(*range._value, std::min(std::ranges::distance(range), diff)); else return views::repeat(*range._value, diff); } template<class Range> constexpr auto drop_of_repeat_view(Range&& range, std::ranges::range_difference_t<Range> diff) { using T = std::remove_cvref_t<Range>; static_assert(is_repeat_view<T>); if constexpr(std::ranges::sized_range<T>) { auto size = std::ranges::distance(range); return views::repeat(*range._value, size - std::min(size, diff)); } else { return range; } } } // namespace internal } // namespace views } // namespace uni #line 2 "view/slide.hpp" #line 6 "view/slide.hpp" #line 9 "view/slide.hpp" #line 11 "view/slide.hpp" namespace uni { namespace internal { template<class View> concept slide_caches_nothing = std::ranges::random_access_range<View> && std::ranges::sized_range<View>; template<class View> concept slide_caches_last = !slide_caches_nothing<View> && std::ranges::bidirectional_range<View> && std::ranges::common_range<View>; template<class View> concept slide_caches_first = !slide_caches_nothing<View> && !slide_caches_last<View>; } // namespace internal template<std::ranges::forward_range View> requires std::ranges::view<View> struct slide_view : std::ranges::view_interface<slide_view<View>> { private: View _base; std::ranges::range_difference_t<View> _n; [[no_unique_address]] internal::maybe_present_t<internal::slide_caches_first<View>, internal::cached_position<View>, 0> _cache_begin; [[no_unique_address]] internal::maybe_present_t<internal::slide_caches_last<View>, internal::cached_position<View>, 1> _cache_end; template<bool> struct iterator; struct sentinel; public: constexpr explicit slide_view(View base, std::ranges::range_difference_t<View> n) : _base(std::move(base)), _n(n) { assert(n > 0); } constexpr auto begin() requires(!(internal::simple_view<View> && internal::slide_caches_nothing<const View>)) { if constexpr(internal::slide_caches_first<View>) { std::ranges::iterator_t<View> itr; if(this->_cache_begin.has_value()) { itr = this->_cache_begin.get(this->_base); } else { itr = std::ranges::next(std::ranges::begin(this->_base), this->_n - 1, std::ranges::end(this->_base)); this->_cache_begin.set(this->_base, itr); } return iterator<false>(std::ranges::begin(this->_base), std::move(itr), this->_n); } else { return iterator<false>(std::ranges::begin(this->_base), this->_n); } } constexpr auto begin() const requires internal::slide_caches_nothing<const View> { return iterator<true>(std::ranges::begin(this->_base), this->_n); } constexpr auto end() requires (!(internal::simple_view<View> && internal::slide_caches_nothing<const View>)) { if constexpr(internal::slide_caches_nothing<View>) { return iterator<false>(std::ranges::begin(this->_base) + std::ranges::range_difference_t<View>(this->size()), this->_n); } else if constexpr(internal::slide_caches_last<View>) { std::ranges::iterator_t<View> itr; if(this->_cache_end.has_value()) { itr = this->_cache_end.get(this->_base); } else { itr = std::ranges::prev(std::ranges::end(this->_base), this->_n - 1, std::ranges::begin(this->_base)); this->_cache_end.set(this->_base, itr); } return iterator<false>(std::move(itr), this->_n); } else if constexpr(std::ranges::common_range<View>) { return iterator<false>(std::ranges::end(this->_base), std::ranges::end(this->_base), this->_n); } else { return sentinel(std::ranges::end(this->_base)); } } constexpr auto end() const requires internal::slide_caches_nothing<const View> { return this->begin() + std::ranges::range_difference_t<const View>(this->size()); } constexpr auto size() requires std::ranges::sized_range<View> { auto size = std::ranges::distance(this->_base) - this->_n + 1; if(size < 0) size = 0; return to_unsigned(size); } constexpr auto size() const requires std::ranges::sized_range<const View> { auto size = std::ranges::distance(this->_base) - this->_n + 1; if(size < 0) size = 0; return to_unsigned(size); } }; template<class Range> slide_view(Range &&, std::ranges::range_difference_t<Range>) -> slide_view<std::views::all_t<Range>>; template<std::ranges::forward_range View> requires std::ranges::view<View> template<bool CONST> struct slide_view<View>::iterator { private: using Base = internal::maybe_const_t<CONST, View>; static constexpr bool LAST_PRESENT = internal::slide_caches_first<Base>; std::ranges::iterator_t<Base> _current = std::ranges::iterator_t<Base>(); [[no_unique_address]] internal::maybe_present_t<LAST_PRESENT, std::ranges::iterator_t<Base>> _last = decltype(_last)(); std::ranges::range_difference_t<Base> _n = 0; constexpr iterator(std::ranges::iterator_t<Base> current, std::ranges::range_difference_t<Base> n) requires (!LAST_PRESENT) : _current(current), _n(n) {} constexpr iterator(std::ranges::iterator_t<Base> current, std::ranges::iterator_t<Base> last, std::ranges::range_difference_t<Base> n) requires (LAST_PRESENT) : _current(current), _last(last), _n(n) {} friend slide_view; friend slide_view::sentinel; public: using iterator_category = std::input_iterator_tag; using iterator_concept = internal::most_primitive_iterator_concept<false, Base>; using value_type = decltype(std::views::counted(_current, _n)); using difference_type = std::ranges::range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!CONST> itr) requires CONST && std::convertible_to<std::ranges::iterator_t<View>, std::ranges::iterator_t<Base>> : _current(std::move(itr._current)), _n(itr._n) {} constexpr auto operator*() const { return std::views::counted(_current, _n); } constexpr iterator &operator++() { ++this->_current; if constexpr(LAST_PRESENT) ++this->_last; return *this; } constexpr iterator operator++(int) { const auto temp = *this; return ++*this, temp; } constexpr iterator &operator--() requires std::ranges::bidirectional_range<Base> { --this->_current; if constexpr(LAST_PRESENT) --this->_last; return *this; } constexpr iterator operator--(int) requires std::ranges::bidirectional_range<Base> { auto temp = *this; return --*this, temp; } constexpr iterator &operator+=(const difference_type rhs) requires std::ranges::random_access_range<Base> { this->_current += rhs; if constexpr(LAST_PRESENT) this->_last += rhs; return *this; } constexpr iterator &operator-=(const difference_type rhs) requires std::ranges::random_access_range<Base> { this->_current -= rhs; if constexpr(LAST_PRESENT) this->_last -= rhs; return *this; } constexpr auto operator[](const difference_type count) const requires std::ranges::random_access_range<Base> { return std::views::counted(this->_current + count, this->_n); } friend constexpr bool operator==(const iterator &lhs, const iterator &rhs) { if constexpr(LAST_PRESENT) return lhs._last == rhs._last; else return lhs._current == rhs._current; } friend constexpr auto operator<=>(const iterator &lhs, const iterator &rhs) requires std::ranges::random_access_range<Base> && std::three_way_comparable<std::ranges::iterator_t<Base>> { return lhs._current <=> rhs._current; } friend constexpr iterator operator+(iterator itr, const difference_type count) requires std::ranges::random_access_range<Base> { auto res = itr; return res += count, res; } friend constexpr iterator operator+(const difference_type count, const iterator &itr) requires std::ranges::random_access_range<Base> { auto res = itr; return res += count, res; } friend constexpr iterator operator-(const iterator &itr, difference_type count) requires std::ranges::random_access_range<Base> { auto res = itr; return res -= count, res; } friend constexpr difference_type operator-(const iterator &lhs, const iterator &rhs) requires std::sized_sentinel_for<std::ranges::iterator_t<Base>, std::ranges::iterator_t<Base>> { if constexpr(LAST_PRESENT) return lhs._last - rhs._last; else return lhs._current - rhs._current; } }; template<std::ranges::forward_range View> requires std::ranges::view<View> struct slide_view<View>::sentinel { private: std::ranges::sentinel_t<View> _end = std::ranges::sentinel_t<View>(); constexpr explicit sentinel(std::ranges::sentinel_t<View> end) : _end(end) {} friend slide_view; public: sentinel() = default; friend constexpr bool operator==(const iterator<false> &lhs, const sentinel &rhs) { return lhs._last == rhs._end; } friend constexpr std::ranges::range_difference_t<View> operator-(const iterator<false> &lhs, const sentinel &rhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { return lhs._last - rhs._end; } friend constexpr std::ranges::range_difference_t<View> operator-(const sentinel &rhs, const iterator<false> &lhs) requires std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>> { return rhs._end - lhs._last; } }; namespace views { namespace internal { template<class Range, class Diff> concept can_slide_view = requires { slide_view(std::declval<Range>(), std::declval<Diff>()); }; } // namespace internal struct Slide : adaptor::range_adaptor<Slide> { template<std::ranges::viewable_range Range, class Diff = std::ranges::range_difference_t<Range>> requires internal::can_slide_view<Range, Diff> constexpr auto operator() [[nodiscard]] (Range &&res, std::type_identity_t<Diff> n) const { return slide_view(std::forward<Range>(res), n); } using adaptor::range_adaptor<Slide>::operator(); static constexpr int arity = 2; static constexpr bool has_simple_extra_args = true; }; inline constexpr Slide slide; } // namespace views } // namespace uni namespace std::ranges { template<class View> inline constexpr bool enable_borrowed_range<uni::slide_view<View>> = enable_borrowed_range<View>; } #line 2 "view/stride.hpp" #line 8 "view/stride.hpp" #line 12 "view/stride.hpp" #line 14 "view/stride.hpp" #line 16 "view/stride.hpp" namespace uni { template<std::ranges::input_range View> requires std::ranges::view<View> struct stride_view : std::ranges::view_interface<stride_view<View>> { private: View _base; std::ranges::range_difference_t<View> _stride; template<bool Const> using Base = internal::maybe_const_t<Const, View>; template<bool Const> struct iterator_tag {}; template<bool Const> requires std::ranges::forward_range<Base<Const>> struct iterator_tag<Const> { private: static constexpr auto _iterator_category() noexcept { using category = typename std::iterator_traits<std::ranges::iterator_t<Base<Const>>>::iterator_category; if constexpr(std::derived_from<category, std::random_access_iterator_tag>) return std::random_access_iterator_tag{}; else return category{}; } public: using iterator_category = decltype(_iterator_category()); }; public: template<bool> class iterator; constexpr explicit stride_view(View base, const std::ranges::range_difference_t<View> stride) noexcept(NO_EXCEPT) : _base(std::move(base)), _stride(stride) { assert(stride > 0); } inline constexpr View base() const & noexcept(NO_EXCEPT) requires std::copy_constructible<View> { return this->_base; } inline constexpr View base() && noexcept(NO_EXCEPT) { return std::move(this->_base); } inline constexpr std::ranges::range_difference_t<View> stride() const noexcept { return this->_stride; } inline constexpr auto begin() noexcept(NO_EXCEPT) requires(!internal::simple_view<View>) { return iterator<false>(this, std::ranges::begin(this->_base)); } inline constexpr auto begin() const noexcept(NO_EXCEPT) requires std::ranges::range<const View> { return iterator<true>(this, std::ranges::begin(this->_base)); } inline constexpr auto end() noexcept(NO_EXCEPT) requires(!internal::simple_view<View>) { if constexpr(std::ranges::common_range<View> && std::ranges::sized_range<View> && std::ranges::forward_range<View>) { const auto missing = (this->_stride - std::ranges::distance(this->_base) % this->_stride) % this->_stride; return iterator<false>(this, std::ranges::end(this->_base), missing); } else if constexpr(std::ranges::common_range<View> && !std::ranges::bidirectional_range<View>) return iterator<false>(this, std::ranges::end(this->_base)); else return std::default_sentinel; } inline constexpr auto end() const noexcept(NO_EXCEPT) requires std::ranges::range<const View> { if constexpr(std::ranges::common_range<const View> && std::ranges::sized_range<const View> && std::ranges::forward_range<const View>) { const auto missing = (this->_stride - std::ranges::distance(this->_base) % this->_stride) % this->_stride; return iterator<true>(this, std::ranges::end(this->_base), missing); } else if constexpr(std::ranges::common_range<const View> && !std::ranges::bidirectional_range<const View>) return iterator<true>(this, std::ranges::end(this->_base)); else return std::default_sentinel; } inline constexpr auto size() noexcept(NO_EXCEPT) requires std::ranges::sized_range<View> { return to_unsigned(div_ceil(std::ranges::distance(this->_base), this->_stride)); } inline constexpr auto size() const noexcept(NO_EXCEPT) requires std::ranges::sized_range<const View> { return to_unsigned(div_ceil(std::ranges::distance(this->_base), this->_stride)); } }; template<class Range> stride_view(Range&& , std::ranges::range_difference_t<Range>) -> stride_view<std::views::all_t<Range>>; template<std::ranges::input_range View> requires std::ranges::view<View> template<bool Const> struct stride_view<View>::iterator : iterator_tag<Const> { private: using Parent = internal::maybe_const_t<Const, stride_view>; using Base = stride_view::Base<Const>; std::ranges::iterator_t<Base> _current = std::ranges::iterator_t<Base>(); std::ranges::sentinel_t<Base> _end = std::ranges::sentinel_t<Base>(); std::ranges::range_difference_t<Base> _stride = 0; std::ranges::range_difference_t<Base> _missing = 0; constexpr iterator(Parent *const parent, const std::ranges::iterator_t<Base> current, const std::ranges::range_difference_t<Base> missing = 0) noexcept(NO_EXCEPT) : _current(std::move(current)), _end(std::ranges::end(parent->_base)), _stride(parent->_stride), _missing(missing) {} friend stride_view; public: using difference_type = std::ranges::range_difference_t<Base>; using value_type = std::ranges::range_value_t<Base>; using iterator_concept = typename internal::iterator_concept<Base>; iterator() noexcept(NO_EXCEPT) requires std::default_initializable<std::ranges::iterator_t<Base>> = default; constexpr iterator(iterator<!Const> itr) noexcept(NO_EXCEPT) requires Const && std::convertible_to<std::ranges::iterator_t<View>, std::ranges::iterator_t<Base>> && std::convertible_to<std::ranges::sentinel_t<View>, std::ranges::sentinel_t<Base>> : _current(std::move(itr._current)), _end(std::move(itr._end)), _stride(itr._stride), _missing(itr._missing) {} inline constexpr std::ranges::iterator_t<Base> base() && noexcept(NO_EXCEPT) { return std::move(this->_current); } inline constexpr const std::ranges::iterator_t<Base>& base() const & noexcept { return this->_current; } inline constexpr decltype(auto) operator*() const noexcept(NO_EXCEPT) { return *this->_current; } inline constexpr iterator& operator++() noexcept(NO_EXCEPT) { assert(this->_current != _end); this->_missing = std::ranges::advance(this->_current, this->_stride, this->_end); return *this; } inline constexpr void operator++(int) noexcept(NO_EXCEPT) { ++*this; } inline constexpr iterator operator++(int) noexcept(NO_EXCEPT) requires std::ranges::forward_range<Base> { const auto res = *this; ++*this; return res; } inline constexpr iterator& operator--() noexcept(NO_EXCEPT) requires std::ranges::bidirectional_range<Base> { std::ranges::advance(this->_current, this->_missing - this->_stride); this->_missing = 0; return *this; } inline constexpr iterator operator--(int) noexcept(NO_EXCEPT) requires std::ranges::bidirectional_range<Base> { const auto res = *this; --*this; return res; } inline constexpr iterator& operator+=(const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { if(diff > 0) { assert(std::ranges::distance(this->_current, this->_end) > this->_stride * (diff - 1)); this->_missing = std::ranges::advance(this->_current, this->_stride * diff, this->_end); } if(diff < 0) { std::ranges::advance(this->_current, this->_stride * diff + this->_missing); this->_missing = 0; } return *this; } inline constexpr iterator& operator-=(const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { return *this += -diff; } inline constexpr decltype(auto) operator[](const difference_type diff) const noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { return *(*this + diff); } friend inline constexpr bool operator==(const iterator& lhs, std::default_sentinel_t) noexcept(NO_EXCEPT) { return lhs._current == lhs._end; } friend inline constexpr bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::equality_comparable<std::ranges::iterator_t<Base>> { return lhs._current == rhs._current; } friend inline constexpr auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> && std::three_way_comparable<std::ranges::iterator_t<Base>> { return lhs._current <=> rhs._current; } friend inline constexpr iterator operator+(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { auto res = itr; res += diff; return res; } friend inline constexpr iterator operator+(const difference_type diff, const iterator& itr) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { return itr + diff; } friend inline constexpr iterator operator-(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires std::ranges::random_access_range<Base> { auto res = itr; res -= diff; return res; } friend inline constexpr const difference_type operator-(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::iterator_t<Base>, std::ranges::iterator_t<Base>> { const auto diff = lhs._current - rhs._current; if constexpr(std::ranges::forward_range<Base>) return (diff + lhs._missing - rhs._missing) / lhs._stride; else if(diff < 0) return -div_ceil(-diff, lhs._stride); else return div_ceil(diff, lhs._stride); } friend inline constexpr const difference_type operator-(std::default_sentinel_t, const iterator& rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::sentinel_t<Base>, std::ranges::iterator_t<Base>> { return div_ceil(rhs._end - rhs._current, rhs._stride); } friend inline constexpr const difference_type operator-(const iterator& lhs, std::default_sentinel_t rhs) noexcept(NO_EXCEPT) requires std::sized_sentinel_for<std::ranges::sentinel_t<Base>, std::ranges::iterator_t<Base>> { return -(rhs - lhs); } friend inline constexpr std::ranges::range_rvalue_reference_t<Base> iter_move(const iterator& itr) noexcept(NO_EXCEPT) { return std::ranges::iter_move(itr._current); } friend inline constexpr void iter_swap(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires std::indirectly_swappable<std::ranges::iterator_t<Base>> { std::ranges::iter_swap(lhs._current, rhs._current); } }; namespace views { namespace internal { template<class Range, class T> concept can_stride_view = requires { stride_view(std::declval<Range>(), std::declval<T>()); }; } struct Stride : adaptor::range_adaptor<Stride> { template<std::ranges::viewable_range Range, class T = std::ranges::range_difference_t<Range>> requires internal::can_stride_view<Range, T> inline constexpr auto operator() [[nodiscard]] (Range&& res, std::type_identity_t<T> diff) const { return stride_view(std::forward<Range>(res), diff); } using adaptor::range_adaptor<Stride>::operator(); static constexpr int arity = 2; static constexpr bool has_simple_call_op = true; }; inline constexpr Stride stride; } // namespace views } // namespace uni namespace std::ranges { template<class View> inline constexpr bool enable_borrowed_range<uni::stride_view<View>> = enable_borrowed_range<View>; } // namespace std::ranges #line 2 "view/zip.hpp" #line 7 "view/zip.hpp" #line 9 "view/zip.hpp" #line 14 "view/zip.hpp" namespace uni { template<std::ranges::input_range... Views> requires(std::ranges::view<Views> && ...) && (sizeof...(Views) > 0) struct zip_view : std::ranges::view_interface<zip_view<Views...>> { private: std::tuple<Views...> _views; public: template<bool> struct iterator; template<bool> struct sentinel; zip_view() = default; constexpr explicit zip_view(Views... views) noexcept(NO_EXCEPT) : _views(std::move(views)...) {} constexpr auto begin() noexcept(NO_EXCEPT) requires(!(internal::simple_view<Views> && ...)) { return iterator<false>(tuple_transform(std::ranges::begin, this->_views)); } constexpr auto begin() const noexcept(NO_EXCEPT) requires(std::ranges::range<const Views> && ...) { return iterator<true>(tuple_transform(std::ranges::begin, this->_views)); } constexpr auto end() noexcept(NO_EXCEPT) requires(!(internal::simple_view<Views> && ...)) { if constexpr(!internal::zip_is_common<Views...>) return sentinel<false>(tuple_transform(std::ranges::end, this->_views)); else if constexpr((std::ranges::random_access_range<Views> && ...)) return begin() + std::iter_difference_t<iterator<false>>(this->size()); else return iterator<false>(tuple_transform(std::ranges::end, this->_views)); } constexpr auto end() const noexcept(NO_EXCEPT) requires(std::ranges::range<const Views> && ...) { if constexpr(!internal::zip_is_common<const Views...>) return sentinel<true>(tuple_transform(std::ranges::end, this->_views)); else if constexpr((std::ranges::random_access_range<const Views> && ...)) return this->begin() + std::iter_difference_t<iterator<true>>(this->size()); else return iterator<true>(tuple_transform(std::ranges::end, _views)); } constexpr auto size() noexcept(NO_EXCEPT) requires(std::ranges::sized_range<Views> && ...) { return std::apply( [](auto... sizes) { using size_type = std::make_unsigned_t<std::common_type_t<decltype(sizes)...>>; return uni::min(size_type(sizes)...); }, tuple_transform(std::ranges::size, _views) ); } constexpr auto size() const noexcept(NO_EXCEPT) requires(std::ranges::sized_range<const Views> && ...) { return std::apply( [](auto... sizes) { using size_type = std::make_unsigned_t<std::common_type_t<decltype(sizes)...>>; return uni::min(size_type(sizes)...); }, tuple_transform(std::ranges::size, _views) ); } }; template<class... Ranges> zip_view(Ranges &&...) -> zip_view<std::views::all_t<Ranges>...>; namespace internal { template<class iterator> constexpr const typename iterator::iterator_collection& get_current(const iterator& itr) noexcept(NO_EXCEPT); } // namespace internal template<std::ranges::input_range... Views> requires(std::ranges::view<Views> && ...) && (sizeof...(Views) > 0) template<bool Const> struct zip_view<Views...>::iterator : internal::zip_view_iterator_category<Const, Views...> { using iterator_collection = internal::tuple_or_pair_t< std::ranges::iterator_t<internal::maybe_const_t<Const, Views>>... >; private: friend struct zip_view; template<bool> friend struct zip_view::sentinel; iterator_collection _current; constexpr explicit iterator(decltype(_current) current) : _current(std::move(current)) {} // template<std::copy_constructible F, std::ranges::input_range... Vs> // requires // (std::ranges::view<Vs> && ...) && (sizeof...(Vs) > 0) && std::is_object_v<F> && // std::regular_invocable<F&, std::ranges::range_reference_t<Vs>...> && // internal::can_reference<std::invoke_result_t<F&, std::ranges::range_reference_t<Vs>...>> // friend struct zip_transform_view; public: using iterator_concept = internal::most_primitive_iterator_concept<Const, Views...>; using value_type = internal::tuple_or_pair_t<std::ranges::range_value_t<internal::maybe_const_t<Const, Views>>...>; using difference_type = std::common_type_t<std::ranges::range_difference_t<internal::maybe_const_t<Const, Views>>...>; iterator() = default; constexpr iterator(iterator<!Const> itr) noexcept(NO_EXCEPT) requires Const && ( std::convertible_to< std::ranges::iterator_t<Views>, std::ranges::iterator_t<internal::maybe_const_t<Const, Views>> > && ... ) : _current(std::move(itr._current)) {} constexpr auto operator*() const noexcept(NO_EXCEPT) { const auto f = [](auto &itr) -> decltype(auto) { return *itr; }; return tuple_transform(f, this->_current); } constexpr iterator& operator++() noexcept(NO_EXCEPT) { tuple_for_each([](auto &itr) { ++itr; }, this->_current); return *this; } constexpr void operator++(int) noexcept(NO_EXCEPT) { ++*this; } constexpr iterator operator++(int) noexcept(NO_EXCEPT) requires internal::all_forward<Const, Views...> { const auto res = *this; ++*this; return res; } constexpr iterator& operator--() noexcept(NO_EXCEPT) requires internal::all_bidirectional<Const, Views...> { tuple_for_each([](auto &itr) { --itr; }, this->_current); return *this; } constexpr iterator operator--(int) noexcept(NO_EXCEPT) requires internal::all_bidirectional<Const, Views...> { const auto res = *this; --*this; return res; } constexpr iterator& operator+=(const difference_type diff) noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { const auto f = [&]<class Itr>(Itr& itr) constexpr noexcept(NO_EXCEPT) { itr += std::iter_difference_t<Itr>(diff); }; tuple_for_each(f, this->_current); return *this; } constexpr iterator& operator-=(const difference_type diff) noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { const auto f = [&]<class Itr>(Itr& itr) constexpr noexcept(NO_EXCEPT) { itr -= std::iter_difference_t<Itr>(diff); }; tuple_for_each(f, this->_current); return *this; } constexpr auto operator[](const difference_type diff) const noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { const auto f = [&]<class Itr>(Itr& itr) constexpr noexcept(NO_EXCEPT) -> decltype(auto) { return itr[std::iter_difference_t<Itr>(diff)]; }; return tuple_transform(f, _current); } friend constexpr bool operator==(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires ( std::equality_comparable< std::ranges::iterator_t<internal::maybe_const_t<Const, Views>> > && ... ) { if constexpr(internal::all_bidirectional<Const, Views...>) return lhs._current == rhs._current; else return [&]<std::size_t... Is>(std::index_sequence<Is...>) constexpr noexcept(NO_EXCEPT) { return ( (std::get<Is>(lhs._current) == std::get<Is>(rhs._current)) || ... ); }(std::make_index_sequence<sizeof...(Views)>{}); } friend constexpr auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { return lhs._current <=> rhs._current; } friend constexpr iterator operator+(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { auto res = itr; res += diff; return res; } friend constexpr iterator operator+(const difference_type diff, const iterator& itr) noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { auto res = itr; res += diff; return res; } friend constexpr iterator operator-(const iterator& itr, const difference_type diff) noexcept(NO_EXCEPT) requires internal::all_random_access<Const, Views...> { auto res = itr; res -= diff; return res; } friend constexpr difference_type operator-(const iterator& lhs, const iterator& rhs) noexcept(NO_EXCEPT) requires ( std::sized_sentinel_for< std::ranges::iterator_t<internal::maybe_const_t<Const, Views>>, std::ranges::iterator_t<internal::maybe_const_t<Const, Views>> > && ... ) { return [&]<std::size_t... Is>(std::index_sequence<Is...>) constexpr noexcept(NO_EXCEPT) { return std::ranges::min( { difference_type(std::get<Is>(lhs._current) - std::get<Is>(rhs._current)) ... }, std::ranges::less{}, [](const difference_type diff) constexpr noexcept(NO_EXCEPT) { return to_unsigned(diff < 0 ? -diff : diff); } ); }(std::make_index_sequence<sizeof...(Views)>{}); } friend constexpr auto iter_move(const iterator& itr) noexcept(NO_EXCEPT) { return tuple_transform(std::ranges::iter_move, itr._current); } friend constexpr void iter_swap(const iterator& lhs, const iterator& res) noexcept(NO_EXCEPT) requires ( std::indirectly_swappable< std::ranges::iterator_t<internal::maybe_const_t<Const, Views>> > && ... ) { [&]<std::size_t... Is>(std::index_sequence<Is...>) constexpr noexcept(NO_EXCEPT) { ( std::ranges::iter_swap(std::get<Is>(lhs._current), std::get<Is>(res._current)), ... ); }(std::make_index_sequence<sizeof...(Views)>{}); } template<class Itr> friend constexpr const typename Itr::iterator_collection& internal::get_current(const Itr&) noexcept(NO_EXCEPT); }; template<class iterator> constexpr const typename iterator::iterator_collection& internal::get_current(const iterator& itr) noexcept(NO_EXCEPT) { return itr._current; }; template<std::ranges::input_range... Views> requires(std::ranges::view<Views> && ...) && (sizeof...(Views) > 0) template<bool Const> struct zip_view<Views...>::sentinel { friend struct zip_view; template<bool> friend struct zip_view::iterator; using sentinel_collection = internal::tuple_or_pair_t< std::ranges::sentinel_t<internal::maybe_const_t<Const, Views>>... >; sentinel_collection _end; constexpr explicit sentinel(sentinel_collection end) noexcept(NO_EXCEPT) : _end(end) {} public: sentinel() = default; constexpr sentinel(sentinel<!Const> itr) noexcept(NO_EXCEPT) requires Const && ( std::convertible_to< std::ranges::sentinel_t<Views>, std::ranges::sentinel_t<internal::maybe_const_t<Const, Views>> > && ... ) : _end(std::move(itr._end)) {} template<bool Const_> requires ( std::sentinel_for< std::ranges::sentinel_t<internal::maybe_const_t<Const, Views>>, std::ranges::iterator_t<internal::maybe_const_t<Const_, Views>> > && ... ) friend constexpr bool operator==(const iterator<Const_>& lhs, const sentinel& rhs) noexcept(NO_EXCEPT) { return [&]<std::size_t... Is>(std::index_sequence<Is...>) constexpr noexcept(NO_EXCEPT) { return ( (std::get<Is>(internal::get_current(lhs)) == std::get<Is>(rhs._end)) || ...); }(std::make_index_sequence<sizeof...(Views)>{}); } template<bool Const_> requires ( std::sized_sentinel_for< std::ranges::sentinel_t<internal::maybe_const_t<Const, Views>>, std::ranges::iterator_t<internal::maybe_const_t<Const_, Views>> > && ... ) friend constexpr auto operator-(const iterator<Const_>& lhs, const sentinel& rhs) noexcept(NO_EXCEPT) { using return_type = std::common_type_t<std::ranges::range_difference_t<internal::maybe_const_t<Const_, Views>>...>; return [&]<std::size_t... Is>(std::index_sequence<Is...>) constexpr noexcept(NO_EXCEPT) { return std::ranges::min( { return_type(std::get<Is>(internal::get_current(lhs)) - std::get<Is>(rhs._end))... }, std::ranges::less{}, [](const return_type diff) { return to_unsigned(diff < 0 ? -diff : diff); } ); }(std::make_index_sequence<sizeof...(Views)>{}); } template<bool Const_> requires ( std::sized_sentinel_for< std::ranges::sentinel_t<internal::maybe_const_t<Const, Views>>, std::ranges::iterator_t<internal::maybe_const_t<Const_, Views>> > && ... ) friend constexpr auto operator-(const sentinel &lhs, const iterator<Const_>& rhs) noexcept(NO_EXCEPT) { return -(rhs - lhs); } }; namespace views { namespace internal { template<class... Ts> concept can_zip_view = requires { zip_view<std::views::all_t<Ts>...>(std::declval<Ts>()...); }; } // namespace internal struct Zip { template<class... Ts> requires(sizeof...(Ts) == 0 || internal::can_zip_view<Ts...>) constexpr auto operator() [[nodiscard]] (Ts&&... vs) const { if constexpr(sizeof...(Ts) == 0) return std::views::empty<std::tuple<>>; else return zip_view<std::views::all_t<Ts>...>(std::forward<Ts>(vs)...); } }; inline constexpr Zip zip; } // namespace views } // namespace uni. namespace std::ranges { template<class... Views> inline constexpr bool enable_borrowed_range<uni::zip_view<Views...>> = (enable_borrowed_range<Views> && ...); } #line 15 "include/all.hpp" #line 2 "random/adaptor.hpp" #line 6 "random/adaptor.hpp" #line 8 "random/adaptor.hpp" namespace uni { template<class Engine> struct random_adaptor { using result_type = typename Engine::result_type; using signed_result_type = typename std::make_signed_t<result_type>; private: Engine engine; public: static constexpr result_type MIN = Engine::min(); static constexpr result_type MAX = Engine::max(); static constexpr result_type min() noexcept(NO_EXCEPT) { return MIN; } static constexpr result_type max() noexcept(NO_EXCEPT) { return MAX; } constexpr random_adaptor(unsigned long seed = 3141592653UL) noexcept(NO_EXCEPT) { this->engine.seed(seed); }; inline constexpr result_type operator()() noexcept(NO_EXCEPT) { return this->engine(); } inline constexpr result_type operator()(const result_type sup) noexcept(NO_EXCEPT) { assert(0 < sup); return this->engine() % sup; } inline constexpr signed_result_type operator()(const signed_result_type min, const signed_result_type sup) noexcept(NO_EXCEPT) { assert(min < sup); return min + (*this)(sup - min); }; template<class T = double> inline constexpr auto real() noexcept(NO_EXCEPT) { const auto v = static_cast<T>((this->engine() + 0.5) / (1.0 + this->max())); return static_cast<T>((this->operator()() + v) / (1.0 + this->max())); } }; } // namespace uni #line 18 "include/all.hpp" #line 2 "utility/restrictor.hpp" #line 4 "utility/restrictor.hpp" #line 6 "utility/restrictor.hpp" namespace uni { template<class T, T INF, T SUP> struct static_restrictor { using restrictor = static_restrictor; protected: T _v = INF; inline void _clamp() noexcept(NO_EXCEPT) { this->_v = std::clamp(this->_v, INF, SUP); } inline restrictor& _assign(const T& v) noexcept(NO_EXCEPT) { this->_v = std::clamp(v, INF, SUP); return *this; } inline restrictor& _assign_raw(const T& v) noexcept(NO_EXCEPT) { this->_v = v; return *this; } public: static_restrictor() noexcept(NO_EXCEPT) = default; static_restrictor(T v) noexcept(NO_EXCEPT) : _v(v) { this->_clamp(); } inline T val() const noexcept(NO_EXCEPT) { return this->_v; } static inline static_restrictor raw(const T& v) noexcept(NO_EXCEPT) { static_restrictor res; res._assign_raw(v); return res; } restrictor& operator++() noexcept(NO_EXCEPT) { return this->_assign(this->_v + 1); } restrictor& operator--() noexcept(NO_EXCEPT) { return this->_assign(this->_v - 1); } restrictor operator++(int) noexcept(NO_EXCEPT) { auto res = *this; return ++(*this), res; } restrictor operator--(int) noexcept(NO_EXCEPT) { auto res = *this; return --(*this), res; } restrictor& operator+=(const restrictor& rhs) noexcept(NO_EXCEPT) { return this->_assign_raw(add_clamp(this->_v, rhs._v, INF, SUP)); } restrictor& operator-=(const restrictor& rhs) noexcept(NO_EXCEPT) { return this->_assign_raw(sub_clamp(this->_v, rhs._v, INF, SUP)); } restrictor& operator*=(const restrictor& rhs) noexcept(NO_EXCEPT) { return this->_assign_raw(mul_clamp(this->_v, rhs._v, INF, SUP)); } restrictor& operator/=(const restrictor& rhs) noexcept(NO_EXCEPT) { return this->_assign(this->_v / rhs.val()); } restrictor operator+() const noexcept(NO_EXCEPT) { return *this; } restrictor operator-() const noexcept(NO_EXCEPT) { return restrictor(-this->_v); } friend restrictor operator+(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs += rhs; } friend restrictor operator-(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs -= rhs; } friend restrictor operator*(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs *= rhs; } friend restrictor operator/(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs /= rhs; } friend bool operator==(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v == rhs._v; } friend bool operator!=(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v != rhs._v; } friend bool operator<(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v < rhs._v; } friend bool operator>(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v > rhs._v; } friend bool operator<=(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v <= rhs._v; } friend bool operator>=(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v >= rhs._v; } friend bool operator<=>(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) { return lhs._v <=> rhs._v; } }; } // namespace uni namespace std { template<class T, T INF, T SUP> T abs(const uni::static_restrictor<T,INF,SUP>& v) noexcept(NO_EXCEPT) { return std::abs(v.val()); } } #line 2 "utility/string.hpp" #line 7 "utility/string.hpp" #line 10 "utility/string.hpp" namespace uni { template<std::input_iterator I, std::sentinel_for<I> S, class Res = std::string> Res to_lower(I first, S last) noexcept(NO_EXCEPT) { Res res; res.reserve(std::ranges::distance(first, last)); std::ranges::transform(first, last, std::back_inserter(res), ::tolower); return res; } template<std::input_iterator I, std::sentinel_for<I> S, class Res = std::string> Res to_uppwer(I first, S last) noexcept(NO_EXCEPT) { Res res; res.reserve(std::ranges::distance(first, last)); std::ranges::transform(first, last, std::back_inserter(res), ::toupper); return res; } template<class Res = std::string> Res to_lower(const std::string str) noexcept(NO_EXCEPT) { return to_lower<std::string::const_iterator, std::string::const_iterator, Res>(std::begin(str), std::end(str)); } template<class Res = std::string> Res to_uppwer(const std::string str) noexcept(NO_EXCEPT) { return to_uppwer<std::string::const_iterator, std::string::const_iterator, Res>(std::begin(str), std::end(str)); } } // namespace uni #line 2 "utility/timer.hpp" #line 7 "utility/timer.hpp" #line 10 "utility/timer.hpp" namespace uni { struct timer { using time_point = std::chrono::milliseconds::rep; using progress_type = long double; private: time_point _time_limit = 0; progress_type progress_duration = 0; std::chrono::system_clock::time_point clock_start, clock_end; public: timer() noexcept = default; explicit timer(const time_point time_limit) noexcept(NO_EXCEPT) { this->reset(time_limit); } inline time_point limit() noexcept(NO_EXCEPT) { return this->_time_limit; } inline timer& reset() noexcept(NO_EXCEPT) { this->clock_start = std::chrono::system_clock::now(); this->clock_end = clock_start + std::chrono::milliseconds(this->_time_limit); return *this; } inline timer& reset(const time_point time_limit) noexcept(NO_EXCEPT) { this->_time_limit = time_limit; this->progress_duration = static_cast<progress_type>( std::chrono::duration_cast<std::chrono::system_clock::duration>( std::chrono::milliseconds(time_limit) ).count() ); return this->reset(); } inline time_point elapsed() const noexcept(NO_EXCEPT) { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - this->clock_start).count(); } inline time_point remaining() const noexcept(NO_EXCEPT) { return _time_limit - this->elapsed(); } inline bool expired() const noexcept(NO_EXCEPT) { return this->elapsed() >= _time_limit; } inline progress_type progress() const noexcept(NO_EXCEPT) { return std::clamp<progress_type>((std::chrono::system_clock::now() - this->clock_start).count() / this->progress_duration, 0, 1); } }; } // namespace uni #line 23 "include/all.hpp" #line 25 "include/all.hpp" #line 28 "include/all.hpp"