#include #ifdef _MSC_VER # include #else # include #endif #include #include namespace suisen { // ! utility template using constraints_t = std::enable_if_t, std::nullptr_t>; template constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) { if constexpr (cond_v) { return std::forward(then); } else { return std::forward(or_else); } } // ! function template using is_same_as_invoke_result = std::is_same, ReturnType>; template using is_uni_op = is_same_as_invoke_result; template using is_bin_op = is_same_as_invoke_result; template using is_comparator = std::is_same, bool>; // ! integral template >> constexpr int bit_num = std::numeric_limits>::digits; template struct is_nbit { static constexpr bool value = bit_num == n; }; template static constexpr bool is_nbit_v = is_nbit::value; // ? template struct safely_multipliable {}; template <> struct safely_multipliable { using type = long long; }; template <> struct safely_multipliable { using type = __int128_t; }; template <> struct safely_multipliable { using type = unsigned long long; }; template <> struct safely_multipliable { using type = __uint128_t; }; template <> struct safely_multipliable { using type = __uint128_t; }; template <> struct safely_multipliable { using type = float; }; template <> struct safely_multipliable { using type = double; }; template <> struct safely_multipliable { using type = long double; }; template using safely_multipliable_t = typename safely_multipliable::type; template struct rec_value_type { using type = T; }; template struct rec_value_type> { using type = typename rec_value_type::type; }; template using rec_value_type_t = typename rec_value_type::type; } // namespace suisen // ! type aliases using i128 = __int128_t; using u128 = __uint128_t; template using pq_greater = std::priority_queue, std::greater>; // ! macros (internal) #define DETAIL_OVERLOAD2(_1,_2,name,...) name #define DETAIL_OVERLOAD3(_1,_2,_3,name,...) name #define DETAIL_OVERLOAD4(_1,_2,_3,_4,name,...) name #define DETAIL_REP4(i,l,r,s) for(std::remove_reference_t>i=(l);i<(r);i+=(s)) #define DETAIL_REP3(i,l,r) DETAIL_REP4(i,l,r,1) #define DETAIL_REP2(i,n) DETAIL_REP3(i,0,n) #define DETAIL_REPINF3(i,l,s) for(std::remove_reference_t>i=(l);;i+=(s)) #define DETAIL_REPINF2(i,l) DETAIL_REPINF3(i,l,1) #define DETAIL_REPINF1(i) DETAIL_REPINF2(i,0) #define DETAIL_RREP4(i,l,r,s) for(std::remove_reference_t>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s)) #define DETAIL_RREP3(i,l,r) DETAIL_RREP4(i,l,r,1) #define DETAIL_RREP2(i,n) DETAIL_RREP3(i,0,n) #define DETAIL_CAT_I(a, b) a##b #define DETAIL_CAT(a, b) DETAIL_CAT_I(a, b) #define DETAIL_UNIQVAR(tag) DETAIL_CAT(tag, __LINE__) // ! macros #define REP(...) DETAIL_OVERLOAD4(__VA_ARGS__, DETAIL_REP4 , DETAIL_REP3 , DETAIL_REP2 )(__VA_ARGS__) #define RREP(...) DETAIL_OVERLOAD4(__VA_ARGS__, DETAIL_RREP4 , DETAIL_RREP3 , DETAIL_RREP2 )(__VA_ARGS__) #define REPINF(...) DETAIL_OVERLOAD3(__VA_ARGS__, DETAIL_REPINF3, DETAIL_REPINF2, DETAIL_REPINF1)(__VA_ARGS__) #define LOOP(n) for (std::remove_reference_t> DETAIL_UNIQVAR(loop_variable) = n; DETAIL_UNIQVAR(loop_variable) --> 0;) #define ALL(iterable) std::begin(iterable), std::end(iterable) #define INPUT(type, ...) type __VA_ARGS__; read(__VA_ARGS__) // ! debug #ifdef LOCAL # define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__) template void debug_internal(const char* s, T&& first, Args&&... args) { constexpr const char* prefix = "[\033[32mDEBUG\033[m] "; constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "("; constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")"; std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward(first); ((std::cerr << ", " << std::forward(args)), ...); std::cerr << close_brakets << "\n"; } #else # define debug(...) void(0) #endif // ! I/O utilities // __int128_t std::ostream& operator<<(std::ostream& dest, __int128_t value) { std::ostream::sentry s(dest); if (s) { __uint128_t tmp = value < 0 ? -value : value; char buffer[128]; char* d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (value < 0) { --d; *d = '-'; } int len = std::end(buffer) - d; if (dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } // __uint128_t std::ostream& operator<<(std::ostream& dest, __uint128_t value) { std::ostream::sentry s(dest); if (s) { char buffer[128]; char* d = std::end(buffer); do { --d; *d = "0123456789"[value % 10]; value /= 10; } while (value != 0); int len = std::end(buffer) - d; if (dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } // pair template std::ostream& operator<<(std::ostream& out, const std::pair& a) { return out << a.first << ' ' << a.second; } // tuple template std::ostream& operator<<(std::ostream& out, const std::tuple& a) { if constexpr (N >= std::tuple_size_v>) return out; else { out << std::get(a); if constexpr (N + 1 < std::tuple_size_v>) out << ' '; return operator<<(out, a); } } // vector template std::ostream& operator<<(std::ostream& out, const std::vector& a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } // array template std::ostream& operator<<(std::ostream& out, const std::array& a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } inline void print() { std::cout << '\n'; } template inline void print(const Head& head, const Tail &...tails) { std::cout << head; if (sizeof...(tails)) std::cout << ' '; print(tails...); } template auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) { for (auto it = v.begin(); it != v.end();) { std::cout << *it; if (++it != v.end()) std::cout << sep; } std::cout << end; } __int128_t stoi128(const std::string& s) { __int128_t ret = 0; for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0'; if (s[0] == '-') ret = -ret; return ret; } __uint128_t stou128(const std::string& s) { __uint128_t ret = 0; for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0'; return ret; } // __int128_t std::istream& operator>>(std::istream& in, __int128_t& v) { std::string s; in >> s; v = stoi128(s); return in; } // __uint128_t std::istream& operator>>(std::istream& in, __uint128_t& v) { std::string s; in >> s; v = stou128(s); return in; } // pair template std::istream& operator>>(std::istream& in, std::pair& a) { return in >> a.first >> a.second; } // tuple template std::istream& operator>>(std::istream& in, std::tuple& a) { if constexpr (N >= std::tuple_size_v>) return in; else return operator>>(in >> std::get(a), a); } // vector template std::istream& operator>>(std::istream& in, std::vector& a) { for (auto it = a.begin(); it != a.end(); ++it) in >> *it; return in; } // array template std::istream& operator>>(std::istream& in, std::array& a) { for (auto it = a.begin(); it != a.end(); ++it) in >> *it; return in; } template void read(Args &...args) { (std::cin >> ... >> args); } // ! integral utilities // Returns pow(-1, n) template constexpr inline int pow_m1(T n) { return -(n & 1) | 1; } // Returns pow(-1, n) template <> constexpr inline int pow_m1(bool n) { return -int(n) | 1; } // Returns floor(x / y) template constexpr inline T fld(const T x, const T y) { return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y; } template constexpr inline T cld(const T x, const T y) { return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y; } template >, std::nullptr_t> = nullptr> __attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); } template , std::nullptr_t> = nullptr> __attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u64(x); } template >, std::nullptr_t> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num; } template , std::nullptr_t> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num; } template >, std::nullptr_t> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num; } template , std::nullptr_t> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num; } template constexpr inline int floor_log2(const T x) { return suisen::bit_num - 1 - count_lz(x); } template constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); } template constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; } template constexpr inline int parity(const T x) { return popcount(x) & 1; } // ! container template auto priqueue_comp(const Comparator comparator) { return std::priority_queue, Comparator>(comparator); } template void sort_unique_erase(Container& a) { std::sort(a.begin(), a.end()); a.erase(std::unique(a.begin(), a.end()), a.end()); } template auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) { if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr); } template auto foreach_adjacent_values(Container &&c, BiConsumer f) -> decltype(c.begin(), c.end(), void()) { foreach_adjacent_values(c.begin(), c.end(), f); } // ! other utilities // x <- min(x, y). returns true iff `x` has chenged. template inline bool chmin(T& x, const T& y) { return y >= x ? false : (x = y, true); } // x <- max(x, y). returns true iff `x` has chenged. template inline bool chmax(T& x, const T& y) { return y <= x ? false : (x = y, true); } template , std::nullptr_t> = nullptr> std::string bin(T val, int bit_num = -1) { std::string res; if (bit_num != -1) { for (int bit = bit_num; bit-- > 0;) res += '0' + ((val >> bit) & 1); } else { for (; val; val >>= 1) res += '0' + (val & 1); std::reverse(res.begin(), res.end()); } return res; } template , std::nullptr_t> = nullptr> std::vector digits_low_to_high(T val, T base = 10) { std::vector res; for (; val; val /= base) res.push_back(val % base); if (res.empty()) res.push_back(T{ 0 }); return res; } template , std::nullptr_t> = nullptr> std::vector digits_high_to_low(T val, T base = 10) { auto res = digits_low_to_high(val, base); std::reverse(res.begin(), res.end()); return res; } template std::string join(const std::vector& v, const std::string& sep, const std::string& end) { std::ostringstream ss; for (auto it = v.begin(); it != v.end();) { ss << *it; if (++it != v.end()) ss << sep; } ss << end; return ss.str(); } template auto transform_to_vector(const Func &f, const Seq &s) { std::vector> v; v.reserve(std::size(s)), std::transform(std::begin(s), std::end(s), std::back_inserter(v), f); return v; } template auto copy_to_vector(const Seq &s) { std::vector v; v.reserve(std::size(s)), std::copy(std::begin(s), std::end(s), std::back_inserter(v)); return v; } template Seq concat(Seq s, const Seq &t) { s.reserve(std::size(s) + std::size(t)); std::copy(std::begin(t), std::end(t), std::back_inserter(s)); return s; } template std::vector split(const Seq s, typename Seq::value_type delim) { std::vector res; for (auto itl = std::begin(s), itr = itl;; itl = ++itr) { while (itr != std::end(s) and *itr != delim) ++itr; res.emplace_back(itl, itr); if (itr == std::end(s)) return res; } } int digit_to_int(char c) { return c - '0'; } int lowercase_to_int(char c) { return c - 'a'; } int uppercase_to_int(char c) { return c - 'A'; } std::vector digit_str_to_ints(const std::string &s) { return transform_to_vector(digit_to_int, s); } std::vector lowercase_str_to_ints(const std::string &s) { return transform_to_vector(lowercase_to_int, s); } std::vector uppercase_str_to_ints(const std::string &s) { return transform_to_vector(uppercase_to_int, s); } const std::string Yes = "Yes", No = "No", YES = "YES", NO = "NO"; namespace suisen {} using namespace suisen; using namespace std; struct io_setup { io_setup(int precision = 20) { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout << std::fixed << std::setprecision(precision); } } io_setup_ {}; // ! code from here #include #include #include #include namespace suisen { struct Mo { Mo() {} Mo(const int n, const std::vector> &queries) : n(n), q(queries.size()), b(bucket_size(n, q)), qs(queries), ord(q) { std::iota(ord.begin(), ord.end(), 0); std::sort( ord.begin(), ord.end(), [&, this](int i, int j) { const auto &[li, ri] = qs[i]; const auto &[lj, rj] = qs[j]; const int bi = li / b, bj = lj / b; if (bi != bj) return bi < bj; if (ri != rj) return bi & 1 ? ri > rj : ri < rj; return li < lj; } ); } // getter methods used in updating functions: AddL, DelL, etc. auto get_left() const { return l; } auto get_right() const { return r; } auto get_range() const { return std::make_pair(l, r); } auto get_query_id() const { return query_id; } /** * [Parameters] * Eval : () -> T : return the current answer * AddL : int -> any (discarded) : add `l` to the current range [l + 1, r) * DelL : int -> any (discarded) : delete `l` from the current range [l, r) * AddR : int -> any (discarded) : add `r` to the current range [l, r) * DelR : int -> any (discarded) : delete `r` from the current range [l, r + 1) * * [Note] * starting from the range [0, 0). */ template auto solve(Eval eval, AddL add_l, DelL del_l, AddR add_r, DelR del_r) { l = 0, r = 0; std::vector res(q); for (int qi : ord) { const auto &[nl, nr] = qs[query_id = qi]; while (r < nr) add_r(r), ++r; while (l > nl) --l, add_l(l); while (r > nr) --r, del_r(r); while (l < nl) del_l(l), ++l; res[qi] = eval(); } return res; } /** * [Parameters] * Eval : () -> T : return the current answer * Add : int -> any (discarded) : add `i` to the current range [i + 1, r) or [l, i) * Del : int -> any (discarded) : delete `i` from the current range [i, r) or [l, i + 1) * * [Note] * starting from the range [0, 0). */ template auto solve(Eval eval, Add add, Del del) { return solve(eval, add, del, add, del); } private: int n, q, b; int query_id = -1; std::vector> qs; std::vector ord; int l = 0, r = 0; static int bucket_size(int n, int q) { return std::max(1, int(::sqrt(3) * n / ::sqrt(std::max(1, 2 * q)))); } }; } // namespace suisen #include #include #include namespace suisen { struct BitVector { explicit BitVector(int n) : n(n), nl((n >> LOG_BLOCK_L) + 1), ns((n >> LOG_BLOCK_S) + 1), cum_l(nl, 0), cum_s(ns, 0), bits(ns, 0) {} BitVector() : BitVector(0) {} template > = nullptr> BitVector(int n, Gen gen) : BitVector(n) { build(gen); } BitVector& operator=(const BitVector& bv) { n = bv.n, nl = bv.nl, ns = bv.ns, cum_l = bv.cum_l, cum_s = bv.cum_s, bits = bv.bits; return *this; } BitVector& operator=(BitVector&& bv) { n = bv.n, nl = bv.nl, ns = bv.ns, cum_l = std::move(bv.cum_l), cum_s = std::move(bv.cum_s), bits = std::move(bv.bits); return *this; } template > = nullptr> void build(Gen gen) { int i = 0; for (int index_s = 1; index_s < ns; ++index_s) { int count = cum_s[index_s - 1]; for (; i < index_s << LOG_BLOCK_S; ++i) { bool b = gen(i); bits[index_s - 1] |= b << (i & MASK_S); count += b; } if (index_s & ((1 << (LOG_BLOCK_L - LOG_BLOCK_S)) - 1)) { cum_s[index_s] = count; } else { int index_l = i >> LOG_BLOCK_L; cum_l[index_l] = cum_l[index_l - 1] + count; } } for (; i < n; ++i) bits[ns - 1] |= gen(i) << (i & MASK_S); } bool operator[](int i) const { return (bits[i >> LOG_BLOCK_S] >> (i & MASK_S)) & 1; } // returns the i'th val (i: 0-indexed) bool access(int i) const { return (*this)[i]; } // returns the number of val in [0, i) int rank(bool val, int i) const { int res_1 = cum_l[i >> LOG_BLOCK_L] + cum_s[i >> LOG_BLOCK_S] + popcount8(bits[i >> LOG_BLOCK_S] & ((1 << (i & MASK_S)) - 1)); return val ? res_1 : i - res_1; } // returns the number of val in [l, r) int rank(bool val, int l, int r) const { return rank(val, r) - rank(val, l); } // find the index of num'th val. (num: 1-indexed). if not exists, returns default_value. int select(bool val, int num, int default_value = -1) const { int l = -1, r = n + 1; while (r - l > 1) { int m = (l + r) >> 1; (rank(val, m) >= num ? r : l) = m; } return r == n + 1 ? default_value : r; } private: static constexpr int LOG_BLOCK_L = 8; static constexpr int LOG_BLOCK_S = 3; static constexpr int MASK_S = (1 << LOG_BLOCK_S) - 1; int n, nl, ns; std::vector cum_l; std::vector cum_s, bits; static constexpr std::uint8_t popcount8(std::uint8_t x) { x = (x & 0b01010101) + ((x >> 1) & 0b01010101); x = (x & 0b00110011) + ((x >> 2) & 0b00110011); return (x & 0b00001111) + (x >> 4); } }; } // namespace suisen namespace suisen { template >::digits> struct WaveletMatrix { // default constructor WaveletMatrix() noexcept : n(0) {} // builds WaveletMatrix from generating function typed as (int) -> T template > = nullptr> WaveletMatrix(int n, Gen generator) : n(n) { build(generator); } // builds WaveletMatrix from vector template > = nullptr> WaveletMatrix(const std::vector& a) : WaveletMatrix(a.size(), [&a](int i) { return T(a[i]); }) {} // builds WaveletMatrix from generating function typed as (int) -> T template > = nullptr> void build(Gen generator) { std::vector a(n), l(n), r(n); for (int i = 0; i < n; ++i) a[i] = generator(i); for (int log = bit_num - 1; log >= 0; --log) { bv[log] = BitVector(n, [&a, log](int i) -> bool { return (a[i] >> log) & 1; }); int li = 0, ri = 0; for (int i = 0; i < n; ++i) { ((a[i] >> log) & 1 ? r[ri++] : l[li++]) = a[i]; } a.swap(l); std::copy(r.begin(), r.begin() + ri, a.begin() + li); mid[log] = li; } } // returns WaveletMatrix[i] T operator[](int i) const { T res = 0; for (int log = bit_num - 1; log >= 0; --log) { bool b = bv[log][i]; res |= T(b) << log; i = b * mid[log] + bv[log].rank(b, i); } return res; } // returns WaveletMatrix[i] T access(int i) const { return (*this)[i]; } // returns the number of `val` in WaveletMatrix[0, i). int rank(T val, int i) const { check_value_bounds(val); int l = 0, r = i; for (int log = bit_num - 1; log >= 0; --log) succ(l, r, (val >> log) & 1, log); return r - l; } // returns the k'th smallest value in the multiset {| x ^ WaveletMatrix[i] : i in [l, r) |} (k : 0-indexed) T range_xor_kth_smallest(int l, int r, int k, T x, T default_value = T(-1)) const { if (k < 0 or k >= r - l) return default_value; T res = 0; check_value_bounds(x); for (int log = bit_num - 1; log >= 0; --log) { bool z = (x >> log) & 1; int cnt_z = bv[log].rank(z, l, r); bool skip_z = k >= cnt_z, bit = z ^ skip_z; succ(l, r, bit, log); res |= T(bit) << log; k -= skip_z * cnt_z; } return res; } // returns the k'th largest value in the multiset {| x ^ WaveletMatrix[i] : i in [l, r) |} (k : 0-indexed) T range_xor_kth_largest(int l, int r, int k, T x, T default_value = T(-1)) const { return range_xor_kth_smallest(l, r, r - l - 1 - k, x, default_value); } // returns the minimum value in the set { x ^ WaveletMatrix[i] : i in [l, r) } T range_xor_min(int l, int r, T x) const { assert(l < r); return range_xor_kth_smallest(l, r, 0, x); } // returns the maximum value in the set { x ^ WaveletMatrix[i] : i in [l, r) } T range_xor_max(int l, int r, T x) const { assert(l < r); return range_xor_kth_largest(l, r, 0, x); } // returns the number of v in WaveletMatrix[l, r) s.t. v ^ x < upper int range_xor_freq(int l, int r, T x, T upper) const { if (r <= l) return 0; if (upper > MAX) return r - l; check_value_bounds(x); int res = 0; for (int log = bit_num - 1; log >= 0; --log) { bool z = (x >> log) & 1, u = (upper >> log) & 1; if (u) res += bv[log].rank(z, l, r); succ(l, r, z ^ u, log); } return res; } // returns the number of v in WaveletMatrix[l, r) s.t. lower <= x ^ v < upper int range_xor_freq(int l, int r, T x, T lower, T upper) const { if (lower >= upper) return 0; return range_xor_freq(l, r, x, upper) - range_xor_freq(l, r, x, lower); } // returns the minimum value v in WaveletMatrix[l, r) s.t. lower <= x ^ v T range_xor_min_geq(int l, int r, T x, T lower, T default_value = T(-1)) const { int cnt = range_xor_freq(l, r, x, lower); return cnt >= r - l ? default_value : range_xor_kth_smallest(l, r, cnt, x); } // returns the minimum value v in WaveletMatrix[l, r) s.t. lower < x ^ v T range_xor_min_gt(int l, int r, T x, T lower, T default_value = T(-1)) const { return lower == MAX ? default_value : range_xor_min_geq(l, r, x, lower + 1, default_value); } // returns the maximum value v in WaveletMatrix[l, r) s.t. x ^ v < upper T range_xor_max_lt(int l, int r, T x, T upper, T default_value = T(-1)) const { int cnt = range_xor_freq(l, r, x, upper); return cnt == 0 ? default_value : range_xor_kth_smallest(l, r, cnt - 1, x, default_value); } // returns the maximum value v in WaveletMatrix[l, r) s.t. x ^ v <= upper T range_xor_max_leq(int l, int r, T x, T upper, T default_value = T(-1)) const { if (l >= r) return default_value; return upper == MAX ? range_xor_max(l, r, x) : range_xor_max_lt(l, r, x, upper + 1, default_value); } // returns the k'th smallest value in WaveletMatrix[l, r) (k : 0-indexed) T range_kth_smallest(int l, int r, int k, T default_value = T(-1)) const { return range_xor_kth_smallest(l, r, k, 0, default_value); } // returns the k'th largest value in WaveletMatrix[l, r) (k : 0-indexed) T range_kth_largest(int l, int r, int k, T default_value = T(-1)) const { return range_xor_kth_largest(l, r, k, 0, default_value); } // returns the minimum value in WaveletMatrix[l, r) T range_min(int l, int r) const { return range_xor_min(l, r, 0); } // returns the maximum value in WaveletMatrix[l, r) T range_max(int l, int r) const { return range_xor_max(l, r, 0); } // returns the number of v in WaveletMatrix[l, r) s.t. v < upper int range_freq(int l, int r, T upper) const { return range_xor_freq(l, r, 0, upper); } // returns the number of v in WaveletMatrix[l, r) s.t. lower <= v < upper int range_freq(int l, int r, T lower, T upper) const { return range_xor_freq(l, r, 0, lower, upper); } // returns the minimum value v in WaveletMatrix[l, r) s.t. lower <= v T range_min_geq(int l, int r, T lower, T default_value = T(-1)) const { return range_xor_min_geq(l, r, 0, lower, default_value); } // returns the minimum value v in WaveletMatrix[l, r) s.t. lower < v T range_min_gt(int l, int r, T lower, T default_value = T(-1)) const { return range_xor_min_gt(l, r, 0, lower, default_value); } // returns the maximum value v in WaveletMatrix[l, r) s.t. v < upper T range_max_lt(int l, int r, T upper, T default_value = T(-1)) const { return range_xor_max_lt(l, r, 0, upper, default_value); } // returns the maximum value v in WaveletMatrix[l, r) s.t. v <= upper T range_max_leq(int l, int r, T upper, T default_value = T(-1)) const { return range_xor_max_leq(l, r, 0, upper, default_value); } protected: WaveletMatrix(int n) noexcept : n(n) {} private: static_assert(bit_num > 0); static constexpr T MAX = bit_num == std::numeric_limits::digits ? std::numeric_limits::max() : (T(1) << bit_num) - 1; int n; std::array bv; std::array mid; void succ(int& l, int& r, const bool b, const int log) const { l = b * mid[log] + bv[log].rank(b, l); r = b * mid[log] + bv[log].rank(b, r); } static void check_value_bounds(T val) { assert((val >> bit_num) == 0); } }; } // namespace suisen int main() { int n, m, q; read(n, m, q); vector> ps(n); for (auto& [p, v] : ps) { read(p); --p; string s; read(s); v = s == "AC"; } vector d(n); REP(i, n) d[i] = ps[i].first; WaveletMatrix wm(d); vector prv(n), nxt(n); vector prv_cnt(n), nxt_cnt(n); { vector pos(m, n), cnt(m, 0); RREP(i, n) { nxt[i] = pos[ps[i].first]; nxt_cnt[i] = cnt[ps[i].first]; if (ps[i].second) { pos[ps[i].first] = i; cnt[ps[i].first] = 0; } else { ++cnt[ps[i].first]; } } } { vector pos(m, -1), cnt(m, 0); REP(i, n) { prv[i] = pos[ps[i].first]; prv_cnt[i] = cnt[ps[i].first]; if (ps[i].second) { pos[ps[i].first] = i; cnt[ps[i].first] = 0; } else { ++cnt[ps[i].first]; } } } vector> qs(q); for (auto &[l, r] : qs) { read(l, r); --l; } Mo mo(n, qs); vector first(m, -1); int ac = 0, wa = 0; auto ans = mo.solve( [&]{ return pair { ac, wa }; }, [&](int l) { auto [p, v] = ps[l]; if (v) { if (first[p] == -1) { ++ac; first[p] = l; } else { wa -= prv_cnt[first[p]]; first[p] = l; } } else { if (first[p] == -1) { // pass } else { ++wa; } } }, [&](int l) { auto [p, v] = ps[l]; if (v) { if (first[p] == -1) { assert(false); } else { int pos = nxt[l]; if (pos < mo.get_right()) { wa += nxt_cnt[l]; } else { --ac; first[p] = -1; } } } else { if (first[p] == -1) { // pass } else { --wa; } } }, [&](int r) { auto [p, v] = ps[r]; if (v) { if (first[p] == -1) { ++ac; int l = mo.get_left(); wa += wm.rank(p, r) - wm.rank(p, l); // REP(i, l, r) if (ps[i].first == p) { // ++wa; // } first[p] = r; } else { // pass } } else { // pass } }, [&](int r) { auto [p, v] = ps[r]; if (v) { if (first[p] == -1) { assert(false); } else { if (first[p] < r) { // pass } else { --ac; int l = mo.get_left(); wa -= wm.rank(p, r) - wm.rank(p, l); // REP(i, l, r) if (ps[i].first == p) { // --wa; // } first[p] = -1; } } } else { // pass } } ); print_all(ans, "\n"); return 0; }