#if __INCLUDE_LEVEL__ == 0 #include __FILE__ void r7h::main(int) { #define let auto const using fp = atcoder::modint1000000007; let n = input(); let a = input>(n); let s = input(); vector> v(n - 1); for (let i : rep(1, n)) { v[i - 1] = {s[i], a[i]}; } let za = atcoder::z_algorithm(v); let suff = reversed(a).scan(fp(0)).to_vla(true); fp ans = suff[0] + a[0] * fp(a[0] - 1) / 2; for (let i : rep(1, n).filter(LAMBDA(s[_1] == s[0]))) { if (a[0] <= a[i]) { ans += a[0] * fp(a[i] - a[0]) + a[0] * fp(a[0] + 1) / 2; if (i + 1 < n && za[i]) { ans += suff[i + 1] - suff[i + za[i] + 1]; if (i + za[i] + 1 < n) { ans += min(a[i + za[i] + 1], a[za[i] + 1]); } } else if (i + 1 < n && s[i + 1] == s[1]) { ans += min(a[i + 1], a[1]); } } else { ans += a[i] * fp(a[i] + 1) / 2; } } println(ans.val()); } #else #define MULTI_CASES 0 #define INTERACTIVE 0 #define USE_INT 1 #ifndef LOCAL #define LOCAL 0 #endif #if !LOCAL #define NDEBUG #endif #ifndef __GLIBCXX_TYPE_INT_N_0 #define __GLIBCXX_TYPE_INT_N_0 __int128 #endif #include #include #include namespace r7h { using namespace std; void main(int); } // namespace r7h #if LOCAL #include #else #define DUMP(...) void(0) #endif #define LIFT(FN) \ [](Ts_&&... xs_) -> decltype(auto) { return FN(static_cast(xs_)...); } #define LAMBDA(...) \ [&]([[maybe_unused]] T1_&& _1 = nullptr, [[maybe_unused]] T2_&& _2 = nullptr) \ -> decltype(auto) { \ return __VA_ARGS__; \ } namespace r7h { template class fix : F { public: explicit fix(F f) : F(move(f)) {} template decltype(auto) operator()(Ts&&... xs) const { return F::operator()(ref(*this), forward(xs)...); } }; template decay_t decay_copy(T&& x) { return forward(x); } template auto ref_or_move(remove_reference_t& x) { if constexpr (is_reference_v && !is_placeholder_v>) { return ref(x); } else { return move(x); } } template > bool const is_lambda_expr = is_placeholder_v || is_bind_expression_v; #define UNARY_LAMBDA(OP) \ template >* = nullptr> \ auto operator OP(T&& x) { \ return bind([](T_&& x_) -> decltype(auto) { return OP forward(x_); }, ref_or_move(x)); \ } #define BINARY_LAMBDA(OP) \ template || is_lambda_expr>* = nullptr> \ auto operator OP(T1&& x, T2&& y) { \ return bind( \ [](T1_&& x_, T2_&& y_) -> decltype(auto) { return forward(x_) OP forward(y_); }, \ ref_or_move(x), ref_or_move(y)); \ } BINARY_LAMBDA(+=) BINARY_LAMBDA(-=) BINARY_LAMBDA(*=) BINARY_LAMBDA(/=) BINARY_LAMBDA(%=) BINARY_LAMBDA(&=) BINARY_LAMBDA(|=) BINARY_LAMBDA(^=) BINARY_LAMBDA(<<=) BINARY_LAMBDA(>>=) UNARY_LAMBDA(++) UNARY_LAMBDA(--) UNARY_LAMBDA(+) UNARY_LAMBDA(-) BINARY_LAMBDA(+) BINARY_LAMBDA(-) BINARY_LAMBDA(*) BINARY_LAMBDA(/) BINARY_LAMBDA(%) UNARY_LAMBDA(~) BINARY_LAMBDA(&) BINARY_LAMBDA(|) BINARY_LAMBDA(^) BINARY_LAMBDA(<<) BINARY_LAMBDA(>>) BINARY_LAMBDA(==) BINARY_LAMBDA(!=) BINARY_LAMBDA(<) BINARY_LAMBDA(>) BINARY_LAMBDA(<=) BINARY_LAMBDA(>=) UNARY_LAMBDA(!) BINARY_LAMBDA(&&) BINARY_LAMBDA(||) #undef UNARY_LAMBDA #undef BINARY_LAMBDA using namespace placeholders; namespace scan_impl { #if INTERACTIVE || LOCAL bool scan(char& c) { return scanf(" %c", &c) != EOF; } bool scan(string& s) { char c; if (!scan(c)) { return false; } for (s = c;; s += c) { c = char(getchar()); if (c <= ' ') { ungetc(c, stdin); break; } } return true; } template enable_if_t, bool> scan(T& x) { char c; if (!scan(c)) { return false; } make_unsigned_t> u = (c == '-' ? getchar() : c) & 15; while (true) { if (int t = getchar(); '0' <= t && t <= '9') { (u *= 10) += t & 15; } else { ungetc(t, stdin); break; } } x = T(c == '-' ? -u : u); return true; } template enable_if_t, bool> scan(T& x) { return scanf(is_same_v ? "%f" : is_same_v ? "%lf" : "%Lf", &x) != EOF; } #else char buf[1 << 15]; char* ptr = buf; char* last = buf; bool scan(char& c) { for (;; ++ptr) { if (last - ptr < 64) { last = move(ptr, last, buf); ptr = buf; last += read(STDIN_FILENO, last, end(buf) - last - 1); *last = '\0'; } if (ptr == last) { return false; } if (' ' < *ptr) { c = *ptr++; return true; } } } bool scan(string& s) { char c; if (!scan(c)) { return false; } for (s = c; ' ' < *ptr; s += c) { scan(c); } return true; } template enable_if_t, bool> scan(T& x) { char c; if (!scan(c)) { return false; } make_unsigned_t> u = (c == '-' ? *ptr++ : c) & 15; while ('0' <= *ptr && *ptr <= '9') { (u *= 10) += *ptr++ & 15; } x = T(c == '-' ? -u : u); return true; } template enable_if_t, bool> scan(T& x) { char c; if (!scan(c)) { return false; } int n; sscanf(--ptr, is_same_v ? "%f%n" : is_same_v ? "%lf%n" : "%Lf%n", &x, &n); ptr += n; return true; } #endif template auto scan(R&& r) -> decltype(begin(r), end(r), true) { return all_of(begin(r), end(r), LIFT(scan)); } template enable_if_t scan(Ts&&... xs) { return (... && scan(forward(xs))); } } // namespace scan_impl using scan_impl::scan; template T input(Args&&... args) { T ret(forward(args)...); [[maybe_unused]] bool res = scan(ret); assert(res); return ret; } namespace print_impl { #if INTERACTIVE || LOCAL template void print(char c) { if (c) { putchar(c); } if (c == '\n') { fflush(stdout); } } template enable_if_t> print(T x) { char buf[64]; char* ptr = to_chars(buf, end(buf), x).ptr; for_each(buf, ptr, LIFT(print)); } template enable_if_t> print(T x) { printf(is_same_v ? "%.6f" : is_same_v ? "%.15f" : "%.18Lf", x); } #else char buf[1 << 15]; char* ptr = buf; __attribute__((destructor)) void flush() { if (write(STDOUT_FILENO, buf, ptr - buf) == -1) { abort(); } ptr = buf; } template void print(char c) { if (end(buf) - ptr < 64) { flush(); } if (c) { *ptr++ = c; } } template enable_if_t> print(T x) { print('\0'); ptr = to_chars(ptr, end(buf), x).ptr; } template enable_if_t> print(T x) { print('\0'); ptr += snprintf(ptr, end(buf) - ptr, is_same_v ? "%.6f" : is_same_v ? "%.15f" : "%.18Lf", x); } #endif template auto print(R&& r) -> void_t { [[maybe_unused]] char c = '\0'; for (auto&& e : r) { if constexpr (!is_same_v, char>) { print(exchange(c, Sep)); } print(e); } } template void print(char const* s) { print(string_view(s)); } template enable_if_t print(Ts&&... xs) { [[maybe_unused]] char c = '\0'; (..., (print(exchange(c, Sep)), print(forward(xs)))); } } // namespace print_impl using print_impl::print; template void println(Ts&&... xs) { print(forward(xs)...); print(End); } #if USE_INT using ptrdiff_t = int; #endif using i8 = signed char; using u8 = unsigned char; using i16 = short; using u16 = unsigned short; using i32 = int; using u32 = unsigned; using i64 = long long; using u64 = unsigned long long; using i128 = __int128; using u128 = unsigned __int128; template struct signed_int; template struct unsigned_int; #define INT_TYPE(N) \ template <> struct signed_int { using type = i##N; }; \ template <> struct unsigned_int { using type = u##N; }; INT_TYPE(8) INT_TYPE(16) INT_TYPE(32) INT_TYPE(64) INT_TYPE(128) #undef INT_TYPE template using signed_int_t = typename signed_int::type; template using unsigned_int_t = typename unsigned_int::type; template class vla { static_assert(1 <= D); array len; T* dat; public: vla() = default; explicit vla(array n) : len(n) { partial_sum(rbegin(len), rend(len), rbegin(len), multiplies()); dat = new T[len[0]]; } explicit vla(array n, T const& val) : vla(n) { fill_n(dat, len[0], val); } vla(vla const& x) : len(x.len), dat(new T[len[0]]) { copy_n(x.dat, len[0], dat); } vla(vla&& x) noexcept : vla() { *this = move(x); } template * = nullptr> explicit vla(ptrdiff_t n) : vla(array{n}) {} template * = nullptr> explicit vla(ptrdiff_t n, T const& val) : vla(array{n}, val) {} vla& operator=(vla const& x) & { return *this = vla(x); } vla& operator=(vla&& x) & noexcept { swap(len, x.len); swap(dat, x.dat); return *this; } ~vla() { delete[] dat; } bool check(ptrdiff_t i) const { return 0 <= i && i < len[0]; } T& operator[](ptrdiff_t i) & { assert(check(i)); return dat[i]; } T const& operator[](ptrdiff_t i) const& { assert(check(i)); return dat[i]; } T operator[](ptrdiff_t i) && { assert(check(i)); return move(dat[i]); } bool check(array i) const { for (int d = 0; d + 1 < D; ++d) { if (i[d] < 0) { return false; } if (len[d] <= i[d] * len[d + 1]) { return false; } } return 0 <= i.back() && i.back() < len.back(); } ptrdiff_t flatten(array i) const { assert(check(i)); return inner_product(i.begin(), i.end() - 1, len.begin() + 1, i.back()); } T& operator[](array i) & { return dat[flatten(i)]; } T const& operator[](array i) const& { return dat[flatten(i)]; } T operator[](array i) && { return move(dat[flatten(i)]); } T* begin() & { return dat; } T const* begin() const& { return dat; } T* end() & { return dat + len[0]; } T const* end() const& { return dat + len[0]; } ptrdiff_t size() const { return len[0]; } }; template auto operator++(T& x, int) -> decltype(++x, T(x)) { T ret = x; ++x; return ret; } template auto operator--(T& x, int) -> decltype(--x, T(x)) { T ret = x; --x; return ret; } #define BINARY_ARITH_OP(OP) \ template > \ auto operator OP(T1 const& x, T2 const& y) -> decltype(declval() OP##= y, T(x)) { \ T ret = T(x); \ ret OP##= y; \ return ret; \ } BINARY_ARITH_OP(+) BINARY_ARITH_OP(-) BINARY_ARITH_OP(*) BINARY_ARITH_OP(/) BINARY_ARITH_OP(%) BINARY_ARITH_OP(&) BINARY_ARITH_OP(|) BINARY_ARITH_OP(^) BINARY_ARITH_OP(<<) BINARY_ARITH_OP(>>) #undef BINARY_ARITH_OP #define COMPARISON_OP(OP, E) \ template \ auto operator OP(T1 const& x, T2 const& y) -> decltype(E) { \ return E; \ } COMPARISON_OP(!=, !(x == y)) COMPARISON_OP(>, y < x) COMPARISON_OP(<=, !(y < x)) COMPARISON_OP(>=, !(x < y)) #undef COMPARISON_OP template class iter_base { D& derived() & { return static_cast(*this); } D const& derived() const& { return static_cast(*this); } bool equal(D const& x) const { return derived().equal(x); } ptrdiff_t dist_to(D const& x) const { return derived().dist_to(x); } public: using iterator_category = C; using value_type = decay_t; using difference_type = ptrdiff_t; using pointer = void; using reference = R; #define REQUIRE(CATEGORY) template >* = nullptr> R operator*() const { return derived().deref(); } REQUIRE(random_access) R operator[](ptrdiff_t n) const { return *(derived() + n); } D& operator++() & { derived().inc(); return derived(); } REQUIRE(bidirectional) D& operator--() & { derived().dec(); return derived(); } REQUIRE(random_access) D& operator+=(ptrdiff_t n) & { derived().advance(n); return derived(); } REQUIRE(random_access) D& operator-=(ptrdiff_t n) & { derived().advance(-n); return derived(); } REQUIRE(random_access) friend D operator+(D const& x, ptrdiff_t n) { D ret = x; ret += n; return ret; } REQUIRE(random_access) friend D operator+(ptrdiff_t n, D const& x) { return x + n; } REQUIRE(random_access) friend D operator-(D const& x, ptrdiff_t n) { D ret = x; ret -= n; return ret; } REQUIRE(random_access) friend ptrdiff_t operator-(D const& x, D const& y) { return static_cast(y).dist_to(x); } friend bool operator==(D const& x, D const& y) { return static_cast(x).equal(y); } REQUIRE(random_access) friend bool operator<(D const& x, D const& y) { return x - y < 0; } #undef REQUIRE }; template class int_iter : public iter_base, random_access_iterator_tag, T> { friend class int_iter::iter_base; T v; T deref() const { return v; } bool equal(int_iter const& x) const { return v == x.v; } void inc() & { ++v; } void dec() & { --v; } void advance(ptrdiff_t n) & { v += T(n); } ptrdiff_t dist_to(int_iter const& x) const { return make_signed_t(x.v - v); } public: int_iter() = default; explicit int_iter(T v) : v(v) {} }; template auto sz(R&& r) -> decltype(ptrdiff_t(size(forward(r)))) { return ptrdiff_t(size(forward(r))); } template T div_floor(T x, T y) { return T(x / y - ((x ^ y) < 0 && x % y)); } template T div_ceil(T x, T y) { return T(x / y + (0 <= (x ^ y) && x % y)); } template bool chmin(T& x, U&& y) { return y < x ? x = forward(y), true : false; } template bool chmax(T& x, U&& y) { return x < y ? x = forward(y), true : false; } template T const inf_v = numeric_limits::max() / 2; int const inf = inf_v; mt19937_64 mt(_rdtsc()); template T rand(T a, T b) { if constexpr (is_integral_v) { return uniform_int_distribution(a, b)(mt); } else { return uniform_real_distribution(a, b)(mt); } } #define TC(...) template TC(R) using iter_t = decltype(begin(declval())); TC(R) using range_cat = typename iterator_traits>::iterator_category; TC(R) using range_ref = typename iterator_traits>::reference; TC() class view_base; #define Z ptrdiff_t #define IIT input_iterator_tag #define FIT forward_iterator_tag #define BIT bidirectional_iterator_tag #define RAIT random_access_iterator_tag #define VIEW(CLS, ...) \ class CLS : public view_base> { \ friend class CLS::view_base; #define VIEW_END(...) \ __VA_OPT__(Z size() const { return __VA_ARGS__; }) \ }; TC(R, class F) VIEW(filtered, R, F) struct iter : iter_base, BIT>, range_ref> { filtered const* p; iter_t i; range_ref deref() const { return *i; } bool equal(iter const& x) const { return i == x.i; } void inc() & { do { ++i; } while (i != end(p->r) && !invoke(p->f, *i)); } void dec() & { do { --i; } while (!invoke(p->f, *i)); } }; R r; [[no_unique_address]] F f; iter b() const { return {{}, this, find_if(begin(r), end(r), ref(f))}; } iter e() const { return {{}, this, end(r)}; } public: explicit filtered(R&& r, F f) : r(forward(r)), f(move(f)) {} VIEW_END() TC(R, class F) filtered(R&&, F) -> filtered; TC(R, class F) VIEW(mapped, R, F) using ref = invoke_result_t>; struct iter : iter_base, RAIT>, ref> { mapped const* p; iter_t i; ref deref() const { return invoke(p->f, *i); } bool equal(iter const& x) const { return i == x.i; } void inc() & { ++i; } void dec() & { --i; } void advance(Z n) & { i += n; } Z dist_to(iter const& x) const { return Z(x.i - i); } }; R r; [[no_unique_address]] F f; iter b() const { return {{}, this, begin(r)}; } iter e() const { return {{}, this, end(r)}; } public: explicit mapped(R&& r, F f) : r(forward(r)), f(move(f)) {} VIEW_END(sz(r)) TC(R, class F) mapped(R&&, F) -> mapped; TC(R) VIEW(taken, R) struct iter : iter_base, FIT>, range_ref> { iter_t i; Z n; range_ref deref() const { return *i; } bool equal(iter const& x) const { return n == x.n; } void inc() & { --n; if (n) { ++i; } } }; R r; Z n; auto b() const { if constexpr (is_convertible_v, RAIT>) { return begin(r); } else { return iter{{}, n ? begin(r) : end(r), n}; } } auto e() const { if constexpr (is_convertible_v, RAIT>) { return begin(r) + size(); } else { return iter{{}, end(r), 0}; } } public: explicit taken(R&& r, Z n) : r(forward(r)), n(max(n, 0)) { assert(0 <= n); } VIEW_END(min(n, sz(r))) TC(R) taken(R&&, Z) -> taken; TC(R, class F) VIEW(taken_while, R, F) static_assert(is_convertible_v, FIT>); struct iter : iter_base, FIT>, range_ref> { taken_while const* p; iter_t i; range_ref deref() const { return *i; } bool equal(iter const& x) const { return i == x.i; } void inc() & { ++i; if (i != end(p->r) && !invoke(p->f, *i)) { i = end(p->r); } } }; R r; [[no_unique_address]] F f; iter b() const { return {{}, this, begin(r) == end(r) || !invoke(f, *begin(r)) ? end(r) : begin(r)}; } iter e() const { return {{}, this, end(r)}; } public: explicit taken_while(R&& r, F f) : r(forward(r)), f(move(f)) {} VIEW_END() TC(R, class F) taken_while(R&&, F) -> taken_while; TC(R) VIEW(dropped, R) R r; Z n; auto b() const { if constexpr (is_convertible_v, RAIT>) { return begin(r) + min(n, sz(r)); } else { auto ret = begin(r); for (Z _ = n; _-- && ret != end(r);) { ++ret; } return ret; } } auto e() const { return end(r); } public: explicit dropped(R&& r, Z n) : r(forward(r)), n(max(n, 0)) { assert(0 <= n); } VIEW_END(max(sz(r), n) - n) TC(R) dropped(R&&, Z) -> dropped; TC(R, class F) VIEW(dropped_while, R, F) R r; [[no_unique_address]] F f; auto b() const { return find_if_not(begin(r), end(r), ref(f)); } auto e() const { return end(r); } public: explicit dropped_while(R&& r, F f) : r(forward(r)), f(move(f)) {} VIEW_END() TC(R, class F) dropped_while(R&&, F) -> dropped_while; TC(R) VIEW(joined, R) using IR = range_ref; static_assert(is_convertible_v, FIT> && is_convertible_v, FIT>); struct iter : iter_base, range_cat, FIT>, range_ref> { joined const* p; iter_t o; iter_t i; range_ref deref() const { return *i; } bool equal(iter const& x) const { return o == x.o && i == x.i; } void inc() & { for (++i; i == end(*o); i = begin(*o)) { if (++o == end(p->r)) { i = {}; return; } } } }; R r; iter b() const { return {{}, this, begin(r), begin(r) == end(r) ? iter_t() : begin(*begin(r))}; } iter e() const { return {{}, this, end(r), {}}; } public: explicit joined(R&& r) : r(forward(r)) {} VIEW_END() TC(R) joined(R&&) -> joined; TC(R) VIEW(reversed, R) R r; auto b() const { return make_reverse_iterator(end(r)); } auto e() const { return make_reverse_iterator(begin(r)); } public: explicit reversed(R&& r) : r(forward(r)) {} VIEW_END(sz(r)) TC(R) reversed(R&&) -> reversed; TC(R) reversed(reversed&) -> reversed&>; TC(R) reversed(reversed const&) -> reversed const&>; TC(R) reversed(reversed&&) -> reversed>; TC(R) VIEW(sliced, R) static_assert(is_convertible_v, FIT>); R r; Z start; Z stop; auto b() const { return next(begin(r), start); } auto e() const { return next(begin(r), stop); } public: explicit sliced(R&& r, Z start, Z stop) : r(forward(r)) { Z n = sz(this->r); if (start < 0) { start += n; } if (stop < 0) { stop += n; } this->start = clamp(start, 0, n); this->stop = clamp(stop, this->start, n); } VIEW_END(stop - start) TC(R) sliced(R&&, Z, Z) -> sliced; TC(R) VIEW(strided, R) struct iter : iter_base, range_ref> { strided const* p; iter_t i; range_ref deref() const { return *i; } bool equal(iter const& x) const { return i == x.i; } void inc() & { if constexpr (is_convertible_v, RAIT>) { i += min(p->s, Z(end(p->r) - i)); } else { for (Z _ = p->s; _-- && i != end(p->r);) { ++i; } } } void dec() & { if (i == end(p->r)) { Z n = sz(p->r); std::advance(i, (n - 1) / p->s * p->s - n); } else { std::advance(i, -p->s); } } void advance(Z n) & { if (n < 0) { dec(); ++n; } i += min(p->s * n, Z(end(p->r) - i)); } Z dist_to(iter const& x) const { Z d = Z(x.i - i); return d < 0 ? div_floor(d, p->s) : div_ceil(d, p->s); } }; R r; Z s; iter b() const { return {{}, this, begin(r)}; } iter e() const { return {{}, this, end(r)}; } public: explicit strided(R&& r, Z s) : r(forward(r)), s(max(s, 1)) { assert(1 <= s); } VIEW_END(div_ceil(sz(r), s)) TC(R) strided(R&&, Z) -> strided; TC(R, class T, class Op) VIEW(scanned, R, T, Op) static_assert(is_convertible_v, FIT>); struct iter : iter_base, FIT>, T> { scanned const* p; T v; iter_t i; T deref() const { return v; } bool equal(iter const& x) const { return i == x.i && p == x.p; } void inc() & { if (i == end(p->r)) { p = nullptr; } else { v = invoke(p->op, move(v), *i); ++i; } } }; R r; T init; [[no_unique_address]] Op op; iter b() const { return {{}, this, init, begin(r)}; } iter e() const { return {{}, nullptr, {}, end(r)}; } public: explicit scanned(R&& r, T init, Op op) : r(forward(r)), init(move(init)), op(move(op)) {} VIEW_END(sz(r) + 1) TC(R, class T, class Op) scanned(R&&, T, Op) -> scanned; TC(R) VIEW(sampled, R) struct iter : iter_base, IIT>, range_ref> { iter_t i; Z rest; Z n; range_ref deref() const { return *i; } bool equal(iter const& x) const { return i == x.i; } void skip() & { while (rest && n <= rand(0, --rest)) { ++i; } --n; } void inc() & { ++i; skip(); } }; R r; Z n; iter b() const { iter ret{{}, begin(r), sz(r), n}; ret.skip(); return ret; } iter e() const { return {{}, end(r), 0, 0}; } public: explicit sampled(R&& r, Z n) : r(forward(r)), n(clamp(n, 0, sz(this->r))) { assert(0 <= n); } VIEW_END(min(n, sz(r))) TC(R) sampled(R&&, Z) -> sampled; TC(D) class view_base { D const& derived() const { return static_cast(*this); } // namespace r7h public: auto begin() const { return derived().b(); } auto end() const { return derived().e(); } bool empty() const { return begin() == end(); } explicit operator bool() const { return begin() != end(); } Z size() const { return Z(end() - begin()); } decltype(auto) front() const { return *begin(); } decltype(auto) back() const { return *prev(end()); } decltype(auto) operator[](Z n) const { return begin()[n]; } #define WRAP(SIG, CLS, ...) \ SIG const& { return CLS(derived() __VA_OPT__(,) __VA_ARGS__); } \ SIG && { return CLS(static_cast(*this) __VA_OPT__(,) __VA_ARGS__); } WRAP(TC(F) auto filter(F f), filtered, move(f)) WRAP(TC(F) auto map(F f), mapped, move(f)) WRAP(template auto elements(), mapped, LIFT(get)) WRAP(auto keys(), mapped, LIFT(get<0>)) WRAP(auto values(), mapped, LIFT(get<1>)) WRAP(auto take(Z n), taken, n) WRAP(TC(F) auto take_while(F f), taken_while, move(f)) WRAP(auto drop(Z n), dropped, n) WRAP(TC(F) auto drop_while(F f), dropped_while, move(f)) WRAP(auto join(), joined) WRAP(auto rev(), reversed) WRAP(auto slice(Z l, Z r), sliced, l, r) WRAP(auto stride(Z s), strided, s) WRAP(TC(T, class Op = plus<>) auto scan(T init, Op op = {}), scanned, move(init), move(op)) WRAP(auto sample(Z n), sampled, n) #undef WRAP #define WRAP(SIG, FN, ...) \ SIG const { \ using Res = decltype(std::FN(begin(), end() __VA_OPT__(,) __VA_ARGS__)); \ if constexpr (is_void_v) { \ std::FN(begin(), end() __VA_OPT__(,) __VA_ARGS__); \ return derived(); \ } else { \ auto res = std::FN(begin(), end() __VA_OPT__(,) __VA_ARGS__); \ if constexpr (is_same_v>) { \ return Z(distance(begin(), move(res))); \ } else { \ return res; \ } \ } \ } WRAP(TC(F) bool all_of(F f), all_of, ref(f)) WRAP(TC(F) bool any_of(F f), any_of, ref(f)) WRAP(TC(F) Z count(F f), count_if, ref(f)) WRAP(TC(F) Z find(F f), find_if, ref(f)) WRAP(TC(F) Z adjacent_find(F f), adjacent_find, ref(f)) WRAP(TC(F) Z remove(F f), remove_if, ref(f)) WRAP(D const& reverse(), reverse) WRAP(D const& shuffle(), shuffle, mt) WRAP(TC(C = equal_to<>) Z unique(C comp = {}), unique, ref(comp)) WRAP(TC(F) bool is_partitioned(F f), is_partitioned, ref(f)) WRAP(TC(F) Z partition(F f), partition, ref(f)) WRAP(TC(F) Z stable_partition(F f), stable_partition, ref(f)) WRAP(TC(F) Z partition_point(F f), partition_point, ref(f)) WRAP(TC(C = less<>) bool is_sorted(C comp = {}), is_sorted, ref(comp)) WRAP(TC(C = less<>) Z is_sorted_until(C comp = {}), is_sorted_until, ref(comp)) WRAP(TC(C = less<>) D const& sort(C comp = {}), sort, ref(comp)) WRAP(TC(C = less<>) D const& stable_sort(C comp = {}), stable_sort, ref(comp)) WRAP(TC(T, class C = less<>) Z lower_bound(T const& val, C comp = {}), lower_bound, val, ref(comp)) WRAP(TC(T, class C = less<>) Z upper_bound(T const& val, C comp = {}), upper_bound, val, ref(comp)) WRAP(TC(T) bool binary_search(T const& val), binary_search, val) WRAP(Z min_element(), min_element) WRAP(Z max_element(), max_element) WRAP(bool next_permutation(), next_permutation) WRAP(bool prev_permutation(), prev_permutation) WRAP(TC(T, class Op = plus<>) T fold(T init, Op op = {}), accumulate, move(init), ref(op)) #undef WRAP TC(F) D const& each(F f) const { for (auto&& e : derived()) { if constexpr (is_invocable_v) { invoke(f, e); } else { invoke(f); } } return derived(); } TC(F) auto max_right(F f) const { return *prev(std::partition_point(next(begin()), end(), ref(f))); } TC(F) auto min_left(F f) const { return *std::partition_point(begin(), prev(end()), not_fn(ref(f))); } TC(Op = plus<>) auto fold1(Op op = {}) const { return accumulate(next(begin()), end(), front(), ref(op)); } template auto to() const { return C(begin(), end()); } auto to_vla(bool reverse = false) const { vla>> ret(derived().size()); if (reverse) { copy(begin(), end(), make_reverse_iterator(ret.end())); } else { copy(begin(), end(), ret.begin()); } return ret; } }; TC(D1, class D2) bool operator==(view_base const& x, view_base const& y) { return equal(begin(x), end(x), begin(y), end(y)); } TC(D1, class D2) bool operator<(view_base const& x, view_base const& y) { return lexicographical_compare(begin(x), end(x), begin(y), end(y)); } TC(R) VIEW(all, R) R r; auto b() const { return begin(r); } auto e() const { return end(r); } public: explicit all(R&& r) : r(forward(r)) {} VIEW_END(sz(r)) TC(R) all(R&&) -> all; TC(T) all(initializer_list) -> all>; TC(I) VIEW(range, I) I first; I last; I b() const { return first; } I e() const { return last; } public: explicit range(I first, I last) : first(move(first)), last(move(last)) {} VIEW_END() TC(T) auto rep(T l, T r) { return range(int_iter(min(l, r)), int_iter(r)); } TC(T) auto rep(T n) { return rep(0, n); } TC(T) auto rep1(T l, T r) { return rep(l, r + 1); } TC(T) auto rep1(T n) { return rep1(1, n); } TC(G) VIEW(generation, G) using T = decay_t>; struct iter : iter_base { generation const* p; T v; T deref() const { return v; } bool equal(iter const& x) const { return p == x.p; } void inc() & { v = invoke(p->gen); } }; [[no_unique_address]] G gen; iter b() const { return {{}, this, invoke(gen)}; } iter e() const { return {{}, nullptr, {}}; } public: explicit generation(G gen) : gen(move(gen)) {} VIEW_END(numeric_limits::max()) TC(T) auto repeat(T val) { return generation([val = move(val)] { return val; }); } TC(T) auto rand_view(T a, T b) { return generation([a, b] { return rand(a, b); }); } TC(T, class F) VIEW(iteration, T, F) struct iter : iter_base { iteration const* p; T v; T deref() const { return v; } bool equal(iter const& x) const { return p == x.p; } void inc() & { v = invoke(p->f, move(v)); } }; T init; [[no_unique_address]] F f; iter b() const { return {{}, this, init}; } iter e() const { return {{}, nullptr, {}}; } public: explicit iteration(T init, F f) : init(move(init)), f(move(f)) {} VIEW_END(numeric_limits::max()) #undef TC #undef Z #undef IIT #undef FIT #undef BIT #undef RAIT #undef VIEW #undef VIEW_END } // namespace r7h int main() { r7h::rep(MULTI_CASES ? r7h::input() : 1).each(r7h::main); } #include #include #endif