#ifdef TODAY_KYOPRO /* */ struct Mono { using Type = ii3; // val, len, even static Type op(Type l, Type r) { auto [lval, llen, leven] = l; auto [rval, rlen, reven] = r; return {lval + rval, llen + rlen, leven + reven}; } static Type id() { return {0, 0, 0}; } }; struct Ope { using Type = ii3; // fi,fl,se static Type op(Type l, Type r) { if(l[1]) { if(!r[1]) { assert(r[2] == 0); l[2] += r[0]; } else { l[0] = l[0] + l[2] + r[0]; l[2] = r[2]; } } else { if(!r[1]) { assert(r[2] == 0); l[0] += r[0]; } else { l[0] += r[0]; l[2] = r[2]; l[1] = 1; } } return l; } static Type id() { return {0, 0, 0}; } }; typename Mono::Type mapping(typename Mono::Type x, typename Ope::Type f) { auto& [val, len, even] = x; ii odd = len - even; auto& [fi, fl, se] = f; val += len * fi; if(fi % 2) swap(even, odd); if(fl) val = odd; val += se * len; if(se % 2) swap(even, odd); return x; } void run() { II(N, Q); VI(A, N); V init(N); rep(i, N) init[i] = {A[i], 1, 1 - A[i] % 2}; SegTreeLazy range(init); rep(Q) { II(T); IDX(L, R); R++; if(T == 1) { range.apply(L, R, {0, 1, 0}); } else if(T == 2) { II(X); range.apply(L, R, {X, 0, 0}); } else { say(range.fold(L, R)[0]); } } } #else // Created: 2026-10-07 03:09:13 // Copied: 2026-10-07 03:27:12 // #define MULTI //------>8-------- begin kyopro_library/template.hpp --------->8------ //---------------->8----------------------------------------------------->8---------------- // // // // // // // // // // // // // // //---------------->8----------------------------------------------------->8---------------- //------>8------ begin kyopro_library/base/include.hpp ------->8------ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; //------>8------- end kyopro_library/base/include.hpp -------->8------ //------>8-------- begin kyopro_library/base/type.hpp -------->8------ using i8 = int8_t; using i16 = int16_t; using i32 = int32_t; using i64 = int64_t; using i128 = __int128_t; using u8 = uint8_t; using u16 = uint16_t; using u32 = uint32_t; using u64 = unsigned long long; using u128 = __uint128_t; using f64 = double; using f80 = long double; using ii = i64; template struct myvec : vector { using vector::vector; T operator[](ii n) const { return this->at(n); } T& operator[](ii n) { return this->at(n); } }; using ll = i64; using ull = u64; using vi = myvec; using vvi = myvec>; using vvvi = myvec>>; using vl = myvec; using vvl = myvec>; using vvvl = myvec>>; using ii3 = array; using ii4 = array; using ii5 = array; using lll = i128; using vlll = myvec; using vvlll = myvec>; using ulll = u128; using ld = f80; using str = string; using vstr = myvec; constexpr ii operator""_ii(ull x) { return static_cast(x); } constexpr lll operator""_lll(ull x) { return static_cast(x); } template using V = myvec; template using VV = myvec>; template using VVV = myvec>>; template using VVVV = myvec>>>; template using VVVVV = myvec>>>>; template using VVVVVV = myvec>>>>>; template using max_pq = priority_queue; template using min_pq = priority_queue, greater>; template using unset = unordered_set; template using unmap = unordered_map; template struct PR : pair { template PR(Args... args) : pair(args...) {} PR() = default; using pair::first; using pair::second; PR& operator+=(const PR& r) { first += r.first; second += r.second; return *this; } PR& operator-=(const PR& r) { first -= r.first; second -= r.second; return *this; } PR& operator*=(const PR& r) { first *= r.first; second *= r.second; return *this; } template PR& operator+=(const S& r) { first += r; second += r; return *this; } template PR& operator-=(const S& r) { first -= r; second -= r; return *this; } template PR& operator*=(const S& r) { first *= r; second *= r; return *this; } PR operator+(const PR& r) const { return PR(*this) += r; } PR operator-(const PR& r) const { return PR(*this) -= r; } PR operator*(const PR& r) const { return PR(*this) *= r; } template PR operator+(const S& r) const { return PR(*this) += r; } template PR operator-(const S& r) const { return PR(*this) -= r; } template PR operator*(const S& r) const { return PR(*this) *= r; } PR operator-() const { return PR{-first, -second}; } }; using pi = PR; using vpi = myvec; using vvpi = myvec>; using pl = PR; using vpl = myvec; using vvpl = myvec>; template struct TR : tuple { using tuple::tuple; T& x = get<0>(*this); U& y = get<1>(*this); V& z = get<2>(*this); TR() : tuple() {} TR(const T& a, const U& b, const V& c) : tuple(a, b, c) {} TR(const TR& other) : tuple(other), x(get<0>(*this)), y(get<1>(*this)), z(get<2>(*this)) {} TR(TR&& other) noexcept : tuple(move(other)), x(get<0>(*this)), y(get<1>(*this)), z(get<2>(*this)) {} TR& operator=(const TR& other) { tuple::operator=(other); return *this; } TR& operator=(TR&& other) noexcept { tuple::operator=(move(other)); return *this; } }; using ti = TR; using vti = myvec; using vvti = myvec>; using tl = TR; using vtl = myvec; using vvtl = myvec>; const i32 INFI = 1e9 + 10; const i64 INFL = 4e18; const i128 INFLL = 1_lll << 120; template constexpr T inf = 0; template <> constexpr i32 inf = INFI; template <> constexpr i64 inf = INFL; template <> constexpr i128 inf = INFLL; template <> constexpr u32 inf = INFI; template <> constexpr u64 inf = INFL; template <> constexpr u128 inf = INFLL; template <> constexpr f64 inf = numeric_limits::infinity(); template <> constexpr f80 inf = numeric_limits::infinity(); istream& operator>>(istream& is, lll& x) { int c = is.peek(); while(c == ' ' || c == '\n') is.get(), c = is.peek(); bool neg = false; if(c == '-') neg = true, is.get(); x = 0; while(isdigit(is.peek())) x = x * 10 + is.get() - '0'; if(neg) x = -x; return is; } ostream& operator<<(ostream& os, lll x) { if(x < 0) os << '-', x = -x; if(x == 0) return os << '0'; string s; while(x > 0) s += char('0' + x % 10), x /= 10; reverse(s.begin(), s.end()); return os << s; } #ifdef TDY lll abs(lll x) { if(x < 0) return -x; return x; } lll gcd(lll a, lll b) { while(b) a %= b, swap(a, b); return a; } #endif //------>8--------- end kyopro_library/base/type.hpp --------->8------ // #include "kyopro_library/base/fastio.hpp" // #include "kyopro_library/base/fastio_impl.hpp" //------>8------- begin kyopro_library/base/macro.hpp -------->8------ #define rep1(n) for(ii i = 0; i < (n); i++) #define rep2(i, n) for(ii i = 0; i < (n); i++) #define rep3(i, a, b) for(ii i = (a); i < (b); i++) #define rep4(i, a, b, c) for(ii i = (a); i < (b); i += (c)) #define rep_overload(a, b, c, d, e, ...) e #define rep(...) rep_overload(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__) #define per1(n) for(ii i = (n) - 1; i >= 0; i--) #define per2(i, n) for(ii i = (n) - 1; i >= 0; i--) #define per3(i, a, b) for(ii i = (b) - 1; i >= (a); i--) #define per4(i, a, b, c) for(ii i = (b) - 1; i >= (a); i -= (c)) #define per_overload(a, b, c, d, e, ...) e #define per(...) per_overload(__VA_ARGS__, per4, per3, per2, per1)(__VA_ARGS__) #define fore(x, a) for(auto& x : a) #define all(v) (v).begin(), (v).end() #define rall(v) (v).rbegin(), (v).rend() #define QYN(q, a, b) ((q) ? (a) : (b)) #define pb push_back #define eb emplace_back #define mkp make_pair #define mkt make_tuple #define fi first #define se second // vの各要素にfを作用させる #define dov(v, f) \ [&]() { \ auto&& _v = (v); \ for(auto& x : _v) \ f(x); \ }() // vの各要素xに対してf(x)からなる配列を返す #define mkv(v, f) \ [&]() { \ auto&& _v = (v); \ using Type = std::decay_t; \ V ret; \ ret.reserve(_v.size()); \ for(const auto& x : _v) \ ret.push_back(f(x)); \ return ret; \ }() // 宣言&入力 #define II(...) \ ii __VA_ARGS__; \ input(__VA_ARGS__) #define LL(...) \ ll __VA_ARGS__; \ input(__VA_ARGS__) #define LLL(...) \ lll __VA_ARGS__; \ input(__VA_ARGS__) #define IDX(...) \ ii __VA_ARGS__; \ input(__VA_ARGS__); \ input_index(__VA_ARGS__) #define STR(...) \ string __VA_ARGS__; \ input(__VA_ARGS__); #define CHR(...) \ char __VA_ARGS__; \ input(__VA_ARGS__); #define LD(...) \ ld __VA_ARGS__; \ input(__VA_ARGS__); #define VI(A, N) \ vector A(N); \ input(A); #define VVI(A, N, M) \ vector> A(N, vector(M)); \ input(A); #define VL(A, N) \ vector A(N); \ input(A); #define VVL(A, N, M) \ vector> A(N, vector(M)); \ input(A); #define VPI(A, N) \ vpi A(N); \ input(A); #define VTI(A, N) \ vti A(N); \ input(A); #define VI2(A, B, N) \ vector A(N), B(N); \ rep(i, N) cin >> A[i] >> B[i]; #define VL2(A, B, N) \ vector A(N), B(N); \ rep(i, N) cin >> A[i] >> B[i]; #define VI3(A, B, C, N) \ vector A(N), B(N), C(N); \ rep(i, N) cin >> A[i] >> B[i] >> C[i]; #define VL3(A, B, C, N) \ vector A(N), B(N), C(N); \ rep(i, N) cin >> A[i] >> B[i] >> C[i]; #define VI4(A, B, C, D, N) \ vector A(N), B(N), C(N), D(N); \ rep(i, N) cin >> A[i] >> B[i] >> C[i] >> D[i]; #define VST(A, N) \ vector A(N); \ input(A); #define IN2(A, B) rep(i, siz(A)) cin >> A[i] >> B[i]; #define IN3(A, B, C) rep(i, siz(A)) cin >> A[i] >> B[i] >> C[i]; #define IN4(A, B, C, D) rep(i, siz(A)) cin >> A[i] >> B[i] >> C[i] >> D[i]; #define IN5(A, B, C, D, E) \ rep(i, siz(A)) cin >> A[i] >> B[i] >> C[i] >> D[i] >> E[i]; //------>8-------- end kyopro_library/base/macro.hpp --------->8------ //------>8--------- begin kyopro_library/base/io.hpp --------->8------ const char NL = '\n'; void flush() { cout.flush(); } const string Yes = "Yes"; const string No = "No"; const string YES = "YES"; const string NO = "NO"; const string ALICE = "Alice"; const string BOB = "Bob"; const string FIRST = "First"; const string SECOND = "Second"; inline string YesNo(bool f) { return f ? Yes : No; } inline string YESNO(bool f) { return f ? YES : NO; } inline string AliBo(bool f) { return f ? ALICE : BOB; } inline string FiSe(bool f) { return f ? FIRST : SECOND; } template istream& operator>>(istream& is, vector>& v) { for(auto& x : v) for(auto& y : x) is >> y; return is; } template istream& operator>>(istream& is, vector& v) { for(auto& x : v) is >> x; return is; } template istream& operator>>(istream& is, pair& p) { is >> p.first >> p.second; return is; } template void input(T&... a) { (cin >> ... >> a); } template void input_index(T& a) { a--; } template void input_index(T& a, Ts&... b) { a--; input_index(b...); } template ostream& operator<<(ostream& os, const pair& p) { os << p.fi << ' ' << p.se; return os; } template ostream& operator<<(ostream& os, const PR& p) { os << p.fi << ' ' << p.se; return os; } template ostream& operator<<(ostream& os, const tuple& t) { os << ' ' << get<0>(t) << ' ' << get<1>(t) << ' ' << get<2>(t); return os; } template ostream& operator<<(ostream& os, const TR& t) { os << ' ' << get<0>(t) << ' ' << get<1>(t) << ' ' << get<2>(t); return os; } template ostream& operator<<(ostream& os, const tuple& t) { os << ' ' << get<0>(t) << ' ' << get<1>(t) << ' ' << get<2>(t) << ' ' << get<3>(t); return os; } template ostream& operator<<(ostream& os, const vector>>& a) { int I = a.size(); for(int i = 0; i < I; i++) { int J = a[i].size(); for(int j = 0; j < J; j++) { int K = a[i][j].size(); for(int k = 0; k < K; k++) { os << a[i][j][k]; if(k != K - 1) os << ' '; } os << NL; } if(i != I - 1) os << NL; } return os; } template ostream& operator<<(ostream& os, const vector>& a) { int I = a.size(); for(int i = 0; i < I; i++) { int J = a[i].size(); for(int j = 0; j < J; j++) { os << a[i][j]; if(j != J - 1) os << ' '; } if(i != I - 1) cout << NL; } return os; } template ostream& operator<<(ostream& os, const vector& a) { int n = a.size(); for(int i = 0; i < n; i++) { os << a[i]; if(i != n - 1) os << ' '; } return os; } template ostream& operator<<(ostream& os, const set& a) { for(auto itr = a.begin(); itr != a.end(); itr++) { os << *itr; if(next(itr) != a.end()) os << ' '; } return os; } template ostream& operator<<(ostream& os, const multiset& a) { for(auto itr = a.begin(); itr != a.end(); itr++) { os << *itr; if(next(itr) != a.end()) os << ' '; } return os; } template ostream& operator<<(ostream& os, const deque& a) { for(auto itr = a.begin(); itr != a.end(); itr++) { os << *itr; if(next(itr) != a.end()) os << ' '; } return os; } template ostream& operator<<(ostream& os, queue a) { while(!a.empty()) { os << a.front(); a.pop(); if(a.size()) os << ' '; } return os; } template ostream& operator<<(ostream& os, priority_queue a) { while(!a.empty()) { os << a.top(); a.pop(); if(a.size()) os << ' '; } return os; } template ostream& operator<<(ostream& os, priority_queue, greater> a) { while(!a.empty()) { os << a.top(); a.pop(); if(a.size()) os << ' '; } return os; } template ostream& operator<<(ostream& os, array a) { for(int i = 0; i < N; i++) { os << a[i]; if(i != N - 1) os << ' '; } return os; } template void put(const T& a, const Ts&... b) { cout << a; (void)(cout << ... << b); } template void line(const T& a, const Ts&... b) { cout << a; (void)(cout << ... << (cout << ' ', b)); cout << ' '; } void say() { cout << '\n'; } template void say(const T& a, const Ts&... b) { cout << a; (void)(cout << ... << (cout << ' ', b)); cout << NL; } void esay() { #ifdef TDY flush(); cerr << NL; #endif } template void esay(const T& a, const Ts&... b) { #ifdef TDY flush(); cerr << a; (void)(cerr << ... << (cerr << ' ', b)); cerr << NL; #endif } #define O(...) \ { \ say(__VA_ARGS__); \ return; \ } //------>8---------- end kyopro_library/base/io.hpp ---------->8------ //------>8-------- begin kyopro_library/base/util.hpp -------->8------ // 便利関数たち // https://trap.jp/post/1224/ template constexpr auto min(T... a) { return min(initializer_list>{a...}); } template constexpr auto max(T... a) { return max(initializer_list>{a...}); } template bool chmin(A& a, B b) { if(a > b) { a = b; return true; } return false; } template bool chmax(A& a, B b) { if(a < b) { a = b; return true; } return false; } // A/B以下の最大の整数 template constexpr common_type_t myfloor(A a, B b) { assert(b != 0); if(b < 0) a = -a, b = -b; return a / b - (a % b < 0); } // A/B以上の最小の整数 template constexpr common_type_t myceil(A a, B b) { assert(b != 0); if(b < 0) a = -a, b = -b; return a / b + (a % b > 0); } // A%B(in [0,B)) template constexpr common_type_t mymod(A a, B b) { assert(b != 0); if(b < 0) b = -b; if(a > 0) return a % b; return (a % b + b) % b; } // LCM template constexpr common_type_t mylcm(A a, B b) { using T = common_type_t; T g = gcd(a, b); return T(a) / g * b; } template inline ii siz(const T& v) { return v.size(); } template T minv(const vector& v) { if(v.empty()) return inf; return *min_element(all(v)); } template T maxv(const vector& v) { if(v.empty()) return -inf; return *max_element(all(v)); } template ii minidx(const V& v) { return min_element(all(v)) - v.begin(); } template ii maxidx(const V& v) { return max_element(all(v)) - v.begin(); } template T sumv(const vector& v) { return reduce(v.begin(), v.end()); } template ii lob(const vector& v, const T& x) { return lower_bound(all(v), x) - v.begin(); } template ii upb(const V& v, const T& x) { return upper_bound(all(v), x) - v.begin(); } template ii findv(const V& v, const T& x) { for(ii i = 0; i < siz(v); i++) if(v[i] == x) return i; return siz(v); } template ii find_lastv(const V& v, const T& x) { for(ii i = siz(v) - 1; i >= 0; i--) if(v[i] == x) return i; return -1; } // do~~ 破壊的に変える // mk~~ 新しく作る // ソート template void doso(T& v) { sort(v.begin(), v.end()); } template T mkso(const T& v) { auto w = v; doso(w); return w; } // 逆順ソート template void dosor(T& v) { sort(v.rbegin(), v.rend()); } template T mksor(const T& v) { auto w = v; dorsort(w); return w; } // ソート→重複削除 template void douniq(V& v) { sort(all(v)); v.erase(unique(v.begin(), v.end()), v.end()); } template V mkuniq(const V& v) { auto w = v; douniq(w); return w; } // 座標圧縮 template V mkcomp(V v) { auto w = v; douniq(w); for(T& x : v) x = lob(w, x); return v; } // aの中のvの個数を返す ii countv(const auto& a, auto v) { return count(a.begin(), a.end(), v); } // aのidx番目にvを挿入する(..., a[idx-1], v, a[idx], ...) void doinsert(auto& a, ii idx, auto v) { assert(idx <= siz(a)); a.insert(a.begin() + idx, v); } auto mkinsert(const auto& a, ii idx, auto v) { auto b = a; doinsert(b, idx, v); return b; } // aのidx番目を削除する void doerase(auto& a, ii idx) { assert(idx < siz(a)); a.erase(a.begin() + idx); } auto mkerase(const auto& a, ii idx) { auto b = a; doerase(b, idx); return b; } // 先頭をoffset個分後ろに void dorotateback(auto& a, ii offset) { offset %= siz(a); rotate(a.begin(), a.end() - offset, a.end()); } // 末尾をoffset個分前の方に void dorotatefront(auto& a, ii offset) { offset %= siz(a); rotate(a.begin(), a.begin() + offset, a.end()); } auto mkpush(const auto& a, auto v) { auto b = a; b.push_back(v); return b; } // aの[l,r)を抜き出す template V mkslice(const V& a, ii l, ii r) { assert(l <= r && l >= 0 && r <= siz(a)); V b(a.begin() + l, a.begin() + r); return b; } // aとbを連結した配列を返す template V mkconcat(const V& a, const V& b) { auto ret = a; ret.reserve(siz(a) + siz(b)); for(auto x : b) ret.push_back(x); return ret; } // aの後ろにbをくっつける // a <<= bと同じ template void doconcat(V& a, const V& b) { for(auto x : b) a.push_back(x); } // a,bから{(a[0],b[0]), (a[1],b[1]), ...}を作る めっちゃ便利 template vector> zip(const vector& a, const vector& b) { ii n = siz(a); vector> ret(n); for(ii i = 0; i < n; i++) ret[i] = {a[i], b[i]}; return ret; } template vector> zip(const vector& a, const vector& b, const vector& c) { ii n = siz(a); vector> ret(n); for(ii i = 0; i < n; i++) ret[i] = {a[i], b[i], c[i]}; return ret; } template PR, vector> unzip(const vector>& p) { ii n = siz(p); vector reta(n); vector retb(n); for(ii i = 0; i < n; i++) { reta[i] = p[i].first; retb[i] = p[i].second; } return mkp(reta, retb); } template TR, vector, vector> unzip(const vector>& p) { ii n = siz(p); vector reta(n); vector retb(n); vector retc(n); for(ii i = 0; i < n; i++) { auto [a, b, c] = p[i]; reta[i] = a; retb[i] = b; retc[i] = c; } return mkt(reta, retb, retc); } template T pick(max_pq& v) { T ret = v.top(); v.pop(); return ret; } template T pick(min_pq& v) { T ret = v.top(); v.pop(); return ret; } template T pick(queue& v) { T ret = v.front(); v.pop(); return ret; } template T pick(vector& v) { T ret = v.back(); v.pop_back(); return ret; } template T pickf(deque& v) { T ret = v.front(); v.pop_front(); return ret; } template T pickb(deque& v) { T ret = v.back(); v.pop_back(); return ret; } template bool nxperm(T& v) { return next_permutation(v.begin(), v.end()); } // 前置インクリメント (++v) template vector& operator++(vector& a) { for(auto& x : a) ++x; return a; } // 後置インクリメント (v++) template vector operator++(vector& a, int) { vector res = a; ++a; return res; } // 前置デクリメント (--v) template vector& operator--(vector& a) { for(auto& x : a) --x; return a; } // 後置デクリメント (v--) template vector operator--(vector& a, int) { vector res = a; --a; return res; } template vector operator>>=(const U& b, vector& a) { a.insert(a.begin(), b); return a; } template vector operator>>(const U& b, vector a) { b >>= a; return a; } template vector operator<<=(vector& a, const U& b) { a.push_back(b); return a; } template void operator<<=(vector& a, const vector& b) { vector ret = a; for(const auto& x : b) ret.push_back(x); a = ret; } template vector operator<<(vector a, const U& b) { a <<= b; return a; } template vector operator<<(vector a, const vector& b) { a <<= b; return a; } // 演算子オーバーロードを一括定義するマクロ #define DEFINE_VECTOR_OP(OP) \ /* vector OP= スカラー */ \ template \ vector& operator OP##=(vector& a, const U & b) { \ for(auto& x : a) x OP## = b; \ return a; \ } \ /* vector OP= vector (ベクトル同士) */ \ template \ vector& operator OP##=(vector& a, const vector& b) { \ assert(a.size() == b.size()); \ for(ii i = 0; i < a.size(); i++) a[i] OP## = b[i]; \ return a; \ } \ /* vector OP スカラー */ \ template \ vector operator OP(vector a, const U & b) { \ a OP## = b; \ return a; \ } \ /* スカラー OP vector */ \ template \ vector operator OP(const U & a, vector b) { \ for(auto& x : b) x = a OP x; \ return b; \ } \ /* vector OP vector (ベクトル同士) */ \ template \ vector operator OP(vector a, const vector& b) { \ a OP## = b; \ return a; \ } DEFINE_VECTOR_OP(+) DEFINE_VECTOR_OP(-) DEFINE_VECTOR_OP(*) DEFINE_VECTOR_OP(/) DEFINE_VECTOR_OP(%) DEFINE_VECTOR_OP(&) DEFINE_VECTOR_OP(|) DEFINE_VECTOR_OP(^) #undef DEFINE_VECTOR_OP // 多次元のvectorを作る // initで型が推論されるので注意 template V mkvec(ii n, T init) { return V(n, init); } template auto mkvec(ii n, Ts... ts) { return V(n, mkvec(ts...)); } // 累積和 template vector mksum(const vector& v) { ii n = siz(v); V ret(n + 1); for(ii i = 0; i < n; i++) ret[i + 1] = ret[i] + v[i]; return ret; } // 累積max template V mkprefmax(const V& v) { ii n = siz(v); V ret(n + 1, -inf); for(ii i = 0; i < n; i++) ret[i + 1] = max(ret[i], v[i]); return ret; } // 累積min template V mkprefmin(const V& v) { ii n = siz(v); V ret(n + 1, inf); for(ii i = 0; i < n; i++) ret[i + 1] = min(ret[i], v[i]); return ret; } template V mksuffmax(const V& v) { ii n = siz(v); V ret(n + 1, -inf); for(ii i = n - 1; i >= 0; i--) ret[i] = max(ret[i + 1], v[i]); return ret; } template V mksuffmin(const V& v) { ii n = siz(v); V ret(n + 1, inf); for(ii i = n - 1; i >= 0; i--) ret[i] = min(ret[i + 1], v[i]); return ret; } vi mkiota(ii n) { vi ret(n); iota(ret.begin(), ret.end(), 0); return ret; } template T mkrev(T A) { reverse(A.begin(), A.end()); return A; } template void dorev(T& A) { reverse(A.begin(), A.end()); } vi mkinv(const vector& A, ii mx = -1) { ii n = siz(A); if(mx == -1) mx = maxv(A) + 1; vi ret(mx); for(ii i = 0; i < n; i++) ret[A[i]] = i; return ret; } template vvi mkinvvec(const vi& A, ii mx = -1) { ii n = siz(A); if(mx == -1) mx = maxv(A) + 1; vvi ret(mx); for(ii i = 0; i < n; i++) ret[A[i]].push_back(i); return ret; } vi mkfreq(const vi& A, ii mx = -1) { ii n = siz(A); if(mx == -1) mx = maxv(A) + 1; vi ret(mx); for(ii i = 0; i < n; i++) ret[A[i]]++; return ret; } template vi mkarg(const vector& A) { vi ret = mkiota(siz(A)); sort(ret.begin(), ret.end(), [&](ii i, ii j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); }); return ret; } template constexpr ii digit_siz(T n) { ii ret = 0; while(n) { ret++; n /= 10; } return ret; } template constexpr vi digits(T n) { vi ret; while(n) { ret.push_back(n % 10); n /= 10; } reverse(ret.begin(), ret.end()); return ret; } template constexpr T intpow(T x, T r) { T ret = 1; while(r) { if(r & 1) ret *= x; x *= x; r >>= 1; } return ret; } constexpr i64 tenpow(ii r) { i64 ret = 1; while(r--) ret *= 10; return ret; } template constexpr T intsqrt(T x) { i64 sq = (T)sqrtl(ld(x)); while(sq * sq > x) sq--; while((sq + 1) * (sq + 1) <= x) sq++; return sq; } template constexpr T euc_dist(auto ax, auto ay, auto bx, auto by) { return T(ax - bx) * (ax - bx) + T(ay - by) * (ay - by); } template constexpr T man_dist(auto ax, auto ay, auto bx, auto by) { return abs(T(ax) - bx) + abs(T(ay) - by); } constexpr ii lotoi(char c) { assert('a' <= c && c <= 'z'); return c - 'a'; } constexpr char itolo(ii i) { assert(0 <= i && i <= 25); return char('a' + i); } constexpr ii hitoi(char c) { assert('A' <= c && c <= 'Z'); return c - 'A'; } constexpr char itohi(ii i) { assert(0 <= i && i <= 25); return char('A' + i); } constexpr ii ctoi(char c) { assert('0' <= c && c <= '9'); return c - '0'; } constexpr char itoc(ii i) { assert(0 <= i && i <= 9); return char('0' + i); } vi stov(const str& s, char base = 'a') { vi ret(s.size()); rep(i, s.size()) ret[i] = s[i] - base; return ret; } str vtos(const vi& a, char base = 'a') { str ret; rep(i, a.size()) ret.push_back(char(base + a[i])); return ret; } constexpr ii popcount(i32 n) { return __builtin_popcount(n); } constexpr ii popcount(i64 n) { return __builtin_popcountll(n); } constexpr ii parity(i32 n) { return __builtin_parity(n); } constexpr ii parity(i64 n) { return __builtin_parityll(n); } // 最上位ビットの位置 constexpr ii topbit(i32 n) { return n ? 31 - __builtin_clz(n) : -1; } constexpr ii topbit(i64 n) { return n ? 63 - __builtin_clzll(n) : -1; } // 2進表現の長さ constexpr ii bitsiz(i32 n) { return n ? 32 - __builtin_clz(n) : 1; } constexpr ii bitsiz(i64 n) { return n ? 64 - __builtin_clzll(n) : 1; } // 最下位ビットの位置 constexpr ii bottombit(i32 n) { return n ? __builtin_ctz(n) : -1; } constexpr ii bottombit(i64 n) { return n ? __builtin_ctzll(n) : -1; } bool ispower2(i32 n) { return n && (n & -n) == n; } constexpr i64 mkmask(ii n) { return (1LL << n) - 1; } bool hasbit(i64 n, ii i) { return (n >> i & 1); } vi mksubset(ii s) { vi ret; ii t = s; do { ret.push_back(t); --t &= s; } while(t != s); return ret; } // 2進数表記を返す string tobinary(i64 n, ii len = 32, bool rev = false) { string ret; for(ii i = 0; i < len; i++) ret += (hasbit(n, rev ? len - 1 - i : i) ? '1' : '0'); return ret; } // Mint有理数の復元用 template str tofraction(const Mint& a) { for(ii deno = 1; deno <= iter; deno++) { Mint inv = ((Mint)deno).inv(); for(ii nume = 0; nume <= iter; nume++) { Mint val = inv * nume; if(val == a) { if(deno == 1) return to_string(nume); return to_string(nume) + "/" + to_string(deno); } else if(-val == a) { if(deno == 1) return to_string(-nume); return to_string(-nume) + "/" + to_string(deno); } } } return "NF"; } //------>8--------- end kyopro_library/base/util.hpp --------->8------ void run(); int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout << fixed << setprecision(15); cerr << fixed << setprecision(7); #ifdef MULTI II(T); rep(t, T) { #ifdef TDY // esay("============ Case: #", t + 1, " ============"); #endif run(); } #else run(); #endif } #ifdef DEBUG #include "./debug.hpp" #else #define debug(...) #define print_line #endif //------>8--------- end kyopro_library/template.hpp ---------->8------ //------>8 begin kyopro_library/data_structure/segtree_lazy.hpp >8------ /// @brief 遅延評価セグメント木 /// @tparam Monoid モノイド /// @tparam Operator 作用素 /// @tparam mapping (モノイドの元,作用素の元)→モノイドの元を返す関数 /// @ref verify: https://judge.yosupo.jp/problem/range_affine_range_sum /// @ref verify: https://judge.yosupo.jp/problem/range_add_range_min /// @ref verify: https://judge.yosupo.jp/problem/range_affine_range_sum_large_array /// @ref verify: https://judge.yosupo.jp/problem/range_set_range_composite template struct SegTreeLazy { using MonoidType = typename Monoid::Type; using OperatorType = typename Operator::Type; SegTreeLazy() = default; /// @brief 要素数 n の遅延セグ木を構築する SegTreeLazy(int n) { this->n = n; dat = vector(n << 1, Monoid::id()); lazy = vector(n << 1, Operator::id()); indices.reserve(100); cand.reserve(100); cand_l.reserve(100); cand_r.reserve(100); } /// @brief 配列 v から遅延セグ木を構築する SegTreeLazy(const vector& v) { this->n = v.size(); dat = vector(n << 1, Monoid::id()); lazy = vector(n << 1, Operator::id()); rep(i, n) dat[i + n] = v[i]; for(int i = n - 1; i > 0; i--) dat[i] = Monoid::op(dat[i << 1], dat[i << 1 | 1]); indices.reserve(100); cand.reserve(100); cand_l.reserve(100); cand_r.reserve(100); } /// @brief i 番目の要素を x に更新する void set(int i, MonoidType x) { generate_indices(i, i + 1); pushdown(); i += n; dat[i] = x; while(i >>= 1) dat[i] = Monoid::op(dat[i << 1], dat[i << 1 | 1]); } /// @brief 区間 [l, r) に x を作用させる void apply(int l, int r, OperatorType x) { if(l == r) return; generate_indices(l, r); pushdown(); l += n; r += n; while(l < r) { if(l & 1) { lazy[l] = Operator::op(lazy[l], x); dat[l] = mapping(dat[l], x); l++; } if(r & 1) { r--; lazy[r] = Operator::op(lazy[r], x); dat[r] = mapping(dat[r], x); } l >>= 1; r >>= 1; } pushup(); } /// @brief 区間 [l, r) のモノイド積を返す MonoidType fold(int l, int r) { if(l == r) return Monoid::id(); generate_indices(l, r); pushdown(); MonoidType retl = Monoid::id(), retr = Monoid::id(); l += n; r += n; while(l < r) { if(l & 1) retl = Monoid::op(retl, dat[l++]); if(r & 1) retr = Monoid::op(dat[--r], retr); l >>= 1; r >>= 1; } return Monoid::op(retl, retr); } /// @brief 区間 [l, x) のモノイド積が f を満たすような最大の x >= l を返す /// @attention `f(Monoid::id())=true` が成り立つ必要がある /// @note O(log(N)) template int find_right(int l, F f) { assert(f(Monoid::id())); if(l == n) return n; generate_indices(l, n); pushdown(); l += n; int r = n + n; cand_l.clear(); cand_r.clear(); while(l < r) { if(l & 1) cand_l.push_back(l++); if(r & 1) cand_r.push_back(--r); l >>= 1; r >>= 1; } cand = cand_l; reverse(all(cand_r)); cand.insert(cand.end(), all(cand_r)); MonoidType val = Monoid::id(); for(int i : cand) { if(f(Monoid::op(val, dat[i]))) { val = Monoid::op(val, dat[i]); } else { while(i < n) { propagate(i); i <<= 1; if(f(Monoid::op(val, dat[i]))) { val = Monoid::op(val, dat[i]); i |= 1; } } return i - n; } } return n; } /// @brief 区間 [x, r) のモノイド積が f を満たすような最小の x<=r を返す /// @attention `f(Monoid::id())=true` が成り立つ必要がある /// @note O(log(N)) template int find_left(int r, F f) { assert(f(Monoid::id())); if(r == 0) return 0; generate_indices(0, r); pushdown(); r += n; int l = n; cand_l.clear(); cand_r.clear(); while(l < r) { if(l & 1) cand_l.push_back(l++); if(r & 1) cand_r.push_back(--r); l >>= 1; r >>= 1; } cand = cand_r; reverse(all(cand_l)); cand.insert(cand.end(), all(cand_l)); MonoidType val = Monoid::id(); for(int i : cand) { if(f(Monoid::op(dat[i], val))) { val = Monoid::op(dat[i], val); } else { while(i < n) { propagate(i); i = (i << 1) | 1; if(f(Monoid::op(dat[i], val))) { val = Monoid::op(dat[i], val); i ^= 1; } } return i - n + 1; } } return 0; } int size() { return n; } MonoidType operator[](int i) { return fold(i, i + 1); } MonoidType get(int i) { return fold(i, i + 1); } private: int n; vector dat; vector lazy; vi indices, cand, cand_l, cand_r; void generate_indices(int l, int r) { indices.clear(); l += n; r += n; int lm = (l / (l & -l)) >> 1, rm = (r / (r & -r)) >> 1; while(l < r) { if(l <= lm) indices.push_back(l); if(r <= rm) indices.push_back(r); l >>= 1; r >>= 1; } while(l) { indices.push_back(l); l >>= 1; } } void propagate(int i) { if(i < n) { lazy[i << 1] = Operator::op(lazy[i << 1], lazy[i]); lazy[i << 1 | 1] = Operator::op(lazy[i << 1 | 1], lazy[i]); dat[i << 1] = mapping(dat[i << 1], lazy[i]); dat[i << 1 | 1] = mapping(dat[i << 1 | 1], lazy[i]); } lazy[i] = Operator::id(); } void pushdown() { for(int j = (int)indices.size() - 1; j >= 0; j--) { int i = indices[j]; propagate(i); } } void pushup() { rep(j, (int)indices.size()) { int i = indices[j]; dat[i] = Monoid::op(dat[i << 1], dat[i << 1 | 1]); } } }; //------>8------ begin kyopro_library/others/monoid.hpp ------>8------ /// @brief モノイド /// @ref verify: https://judge.yosupo.jp/problem/staticrmq namespace Monoid { /// @brief Minモノイド /// @tparam max_value 単位元 template > struct Min { using Type = T; static Type id() { return max_value; } static Type op(const Type& a, const Type& b) { return min(a, b); } }; /// @brief Maxモノイド /// @tparam min_value 単位元 template > struct Max { using Type = T; static Type id() { return min_value; } static Type op(const Type& a, const Type& b) { return max(a, b); } }; /// @brief 和 template struct Sum { using Type = T; static Type id() { return 0; } static Type op(const Type& a, const Type& b) { return a + b; } }; /// @brief (和,区間の長さ) template struct SumPair { using Type = pair; static Type id() { return make_pair(T(0), 0); } static Type op(const Type& a, const Type& b) { return {a.first + b.first, a.second + b.second}; } }; template struct Update { using Type = T; static Type id() { return not_exist; } static Type op(const Type& a, const Type& b) { return b == id() ? a : b; } }; /// @brief 一次関数 f(x) = a x + b の合成モノイド /// @details Type は pair = (a, b)。op(f, g) は「f を適用してから g を適用する」合成 g∘f を返す。 /// セグ木の fold(l, r) はそのまま f_{r-1}(...f_l(x)) の合成になる。 /// @tparam T 係数の型(modint など、+ と * を持つ体) template struct Affine { using Type = pair; static Type id() { return {T(1), T(0)}; } static Type op(const Type& f, const Type& g) { /* g(f(x)) = g.a (f.a x + f.b) + g.b = (g.a f.a) x + (g.a f.b + g.b) */ return {g.first * f.first, g.first * f.second + g.second}; } /// @brief f(x) を評価する static T eval(const Type& f, const T& x) { return f.first * x + f.second; } }; /// @brief 多数決(Boyer–Moore)モノイド。Type = (候補, 票差)。区間に過半数の要素があれば候補はそれに一致する /// @details 候補が本当に過半数かは別途出現回数を数えて確認する必要がある template struct BoyerMoore { using Type = pair; static Type id() { return {T(), 0}; } static Type op(const Type& a, const Type& b) { /* 同じ候補なら票を足す。違えば票の多い方が残り、票差は減る(過半数の要素は決して打ち消し切られない) */ if(a.first == b.first) return {a.first, a.second + b.second}; if(a.second >= b.second) return {a.first, a.second - b.second}; return {b.first, b.second - a.second}; } }; } // namespace Monoid //------>8------- end kyopro_library/others/monoid.hpp ------->8------ namespace RangeQuery { /// @brief 区間更新 / 区間min /// @tparam max_value 最大値 /// @tparam not_exist 存在しない値 template struct ApplyUpdate_GetMin { static T mapping(const T& a, const T& b) { return b == not_exist ? a : b; } using Type = struct SegTreeLazy, Monoid::Update, mapping>; }; /// @brief 区間更新 / 区間max /// @tparam min_value 最小値 /// @tparam not_exist 存在しない値 template struct ApplyUpdate_GetMax { static T mapping(const T& a, const T& b) { return b == not_exist ? a : b; } using Type = struct SegTreeLazy, Monoid::Update, mapping>; }; /// @brief 区間更新 / 区間和 /// @tparam not_exist 存在しない値 template struct ApplyUpdate_GetSum { using S = typename Monoid::SumPair::Type; static S mapping(const S& a, const T& b) { return b == not_exist ? a : S{b * a.second, a.second}; } using Type = struct SegTreeLazy, Monoid::Update, mapping>; }; /// @brief 区間加算 / 区間min template struct ApplyAdd_GetMin { static T mapping(const T& a, const T& b) { return a + b; } using Type = struct SegTreeLazy, Monoid::Sum, mapping>; }; /// @brief 区間加算 / 区間max template struct ApplyAdd_GetMax { static T mapping(const T& a, const T& b) { return a + b; } using Type = struct SegTreeLazy, Monoid::Sum, mapping>; }; /// @brief 区間加算 / 区間和 template struct ApplyAdd_GetSum { using S = typename Monoid::SumPair::Type; static S mapping(const S& a, const T& b) { return {a.first + b * a.second, a.second}; } using Type = struct SegTreeLazy, Monoid::Sum, mapping>; }; } // namespace RangeQuery //------>8 end kyopro_library/data_structure/segtree_lazy.hpp >8------ // #include #define TODAY_KYOPRO #include __FILE__ #endif // b.cpp // 2026-10-07 03:27:12