This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub fffelix-huang/CP-stuff
#define PROBLEM "https://judge.yosupo.jp/problem/dynamic_sequence_range_affine_range_sum" #include <iostream> #include <vector> #include "../../../library/modint/modint.hpp" #include "../../../library/data-structure/treap.hpp" using namespace std; using namespace felix; using mint = modint998244353; struct S { mint sum; int sz = 0; S() {} S(mint x, int y = 1) : sum(x), sz(y) {} }; S e() { return S(); } S op(S a, S b) { return S(a.sum + b.sum, a.sz + b.sz); } S reversal(S s) { return s; } struct F { mint a = 1, b = 0; F() {} F(mint x, mint y) : a(x), b(y) {} bool operator!=(const F& other) const { return a != other.a || b != other.b; } }; F id() { return F(); } S mapping(F f, S s) { s.sum = f.a * s.sum + f.b * s.sz; return s; } F composition(F a, F b) { return F(a.a * b.a, a.a * b.b + a.b); } int main() { ios::sync_with_stdio(false); cin.tie(0); int n, q; cin >> n >> q; treap<S, e, op, reversal, F, id, mapping, composition> tree; for(int i = 0; i < n; i++) { mint x; cin >> x; tree.insert(tree.end(), S(x)); } while(q--) { int type; cin >> type; if(type == 0) { int p, x; cin >> p >> x; tree.insert_k(p, S(x)); } else if(type == 1) { int p; cin >> p; tree.erase_k(p); } else if(type == 2) { int l, r; cin >> l >> r; tree.reverse(l, r); } else if(type == 3) { int l, r, a, b; cin >> l >> r >> a >> b; tree.apply(l, r, F(a, b)); } else { int l, r; cin >> l >> r; cout << tree.prod(l, r).sum << "\n"; } } return 0; }
#line 1 "test/data-structure/treap/yosupo-Dynamic-Sequence-Range-Affine-Range-Sum.test.cpp" #define PROBLEM "https://judge.yosupo.jp/problem/dynamic_sequence_range_affine_range_sum" #include <iostream> #include <vector> #line 4 "library/modint/modint.hpp" #include <algorithm> #include <cassert> #include <type_traits> #line 3 "library/misc/type-traits.hpp" #include <numeric> #line 5 "library/misc/type-traits.hpp" namespace felix { namespace internal { #ifndef _MSC_VER template<class T> using is_signed_int128 = typename std::conditional<std::is_same<T, __int128_t>::value || std::is_same<T, __int128>::value, std::true_type, std::false_type>::type; template<class T> using is_unsigned_int128 = typename std::conditional<std::is_same<T, __uint128_t>::value || std::is_same<T, unsigned __int128>::value, std::true_type, std::false_type>::type; template<class T> using make_unsigned_int128 = typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t, unsigned __int128>; template<class T> using is_integral = typename std::conditional<std::is_integral<T>::value || is_signed_int128<T>::value || is_unsigned_int128<T>::value, std::true_type, std::false_type>::type; template<class T> using is_signed_int = typename std::conditional<(is_integral<T>::value && std::is_signed<T>::value) || is_signed_int128<T>::value, std::true_type, std::false_type>::type; template<class T> using is_unsigned_int = typename std::conditional<(is_integral<T>::value && std::is_unsigned<T>::value) || is_unsigned_int128<T>::value, std::true_type, std::false_type>::type; template<class T> using to_unsigned = typename std::conditional<is_signed_int128<T>::value, make_unsigned_int128<T>, typename std::conditional<std::is_signed<T>::value, std::make_unsigned<T>, std::common_type<T>>::type>::type; #else template<class T> using is_integral = typename std::is_integral<T>; template<class T> using is_signed_int = typename std::conditional<is_integral<T>::value && std::is_signed<T>::value, std::true_type, std::false_type>::type; template<class T> using is_unsigned_int = typename std::conditional<is_integral<T>::value && std::is_unsigned<T>::value, std::true_type, std::false_type>::type; template<class T> using to_unsigned = typename std::conditional<is_signed_int<T>::value, std::make_unsigned<T>, std::common_type<T>>::type; #endif template<class T> using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>; template<class T> using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>; template<class T> using to_unsigned_t = typename to_unsigned<T>::type; template<class T> struct safely_multipliable {}; template<> struct safely_multipliable<short> { using type = int; }; template<> struct safely_multipliable<unsigned short> { using type = unsigned int; }; template<> struct safely_multipliable<int> { using type = long long; }; template<> struct safely_multipliable<unsigned int> { using type = unsigned long long; }; template<> struct safely_multipliable<long long> { using type = __int128; }; template<> struct safely_multipliable<unsigned long long> { using type = __uint128_t; }; template<class T> using safely_multipliable_t = typename safely_multipliable<T>::type; } // namespace internal } // namespace felix #line 2 "library/math/safe-mod.hpp" namespace felix { namespace internal { template<class T> constexpr T safe_mod(T x, T m) { x %= m; if(x < 0) { x += m; } return x; } } // namespace internal } // namespace felix #line 3 "library/math/inv-gcd.hpp" namespace felix { namespace internal { template<class T> constexpr std::pair<T, T> inv_gcd(T a, T b) { a = safe_mod(a, b); if(a == 0) { return {b, 0}; } T s = b, t = a; T m0 = 0, m1 = 1; while(t) { T u = s / t; s -= t * u; m0 -= m1 * u; auto tmp = s; s = t; t = tmp; tmp = m0; m0 = m1; m1 = tmp; } if(m0 < 0) { m0 += b / s; } return {s, m0}; } } // namespace internal } // namespace felix #line 9 "library/modint/modint.hpp" namespace felix { template<int id> struct modint { public: static constexpr int mod() { return (id > 0 ? id : md); } static constexpr void set_mod(int m) { if(id > 0 || md == m) { return; } md = m; fact.resize(1); inv_fact.resize(1); invs.resize(1); } static constexpr void prepare(int n) { int sz = (int) fact.size(); if(sz == mod()) { return; } n = 1 << std::__lg(2 * n - 1); if(n < sz) { return; } if(n < (sz - 1) * 2) { n = std::min((sz - 1) * 2, mod() - 1); } fact.resize(n + 1); inv_fact.resize(n + 1); invs.resize(n + 1); for(int i = sz; i <= n; i++) { fact[i] = fact[i - 1] * i; } auto eg = internal::inv_gcd(fact.back().val(), mod()); assert(eg.first == 1); inv_fact[n] = eg.second; for(int i = n - 1; i >= sz; i--) { inv_fact[i] = inv_fact[i + 1] * (i + 1); } for(int i = n; i >= sz; i--) { invs[i] = inv_fact[i] * fact[i - 1]; } } constexpr modint() : v(0) {} template<class T, internal::is_signed_int_t<T>* = nullptr> constexpr modint(T x) : v(x >= 0 ? x % mod() : x % mod() + mod()) {} template<class T, internal::is_unsigned_int_t<T>* = nullptr> constexpr modint(T x) : v(x % mod()) {} constexpr int val() const { return v; } constexpr modint inv() const { if(id > 0 && v < std::min(mod() >> 1, 1 << 18)) { prepare(v); return invs[v]; } else { auto eg = internal::inv_gcd(v, mod()); assert(eg.first == 1); return eg.second; } } constexpr modint& operator+=(const modint& rhs) & { v += rhs.v; if(v >= mod()) { v -= mod(); } return *this; } constexpr modint& operator-=(const modint& rhs) & { v -= rhs.v; if(v < 0) { v += mod(); } return *this; } constexpr modint& operator*=(const modint& rhs) & { v = 1LL * v * rhs.v % mod(); return *this; } constexpr modint& operator/=(const modint& rhs) & { return *this *= rhs.inv(); } friend constexpr modint operator+(modint lhs, modint rhs) { return lhs += rhs; } friend constexpr modint operator-(modint lhs, modint rhs) { return lhs -= rhs; } friend constexpr modint operator*(modint lhs, modint rhs) { return lhs *= rhs; } friend constexpr modint operator/(modint lhs, modint rhs) { return lhs /= rhs; } constexpr modint operator+() const { return *this; } constexpr modint operator-() const { return modint() - *this; } constexpr bool operator==(const modint& rhs) const { return v == rhs.v; } constexpr bool operator!=(const modint& rhs) const { return v != rhs.v; } constexpr modint pow(long long p) const { modint a(*this), res(1); if(p < 0) { a = a.inv(); p = -p; } while(p) { if(p & 1) { res *= a; } a *= a; p >>= 1; } return res; } constexpr bool has_sqrt() const { if(mod() == 2 || v == 0) { return true; } if(pow((mod() - 1) / 2).val() != 1) { return false; } return true; } constexpr modint sqrt() const { if(mod() == 2 || v < 2) { return *this; } assert(pow((mod() - 1) / 2).val() == 1); modint b = 1; while(b.pow((mod() - 1) >> 1).val() == 1) { b += 1; } int m = mod() - 1, e = __builtin_ctz(m); m >>= e; modint x = modint(*this).pow((m - 1) >> 1); modint y = modint(*this) * x * x; x *= v; modint z = b.pow(m); while(y.val() != 1) { int j = 0; modint t = y; while(t.val() != 1) { t *= t; j++; } z = z.pow(1LL << (e - j - 1)); x *= z, z *= z, y *= z; e = j; } return x; } friend std::istream& operator>>(std::istream& in, modint& num) { long long x; in >> x; num = modint<id>(x); return in; } friend std::ostream& operator<<(std::ostream& out, const modint& num) { return out << num.val(); } public: static std::vector<modint> fact, inv_fact, invs; private: int v; static int md; }; template<int id> int modint<id>::md = 998244353; template<int id> std::vector<modint<id>> modint<id>::fact = {1}; template<int id> std::vector<modint<id>> modint<id>::inv_fact = {1}; template<int id> std::vector<modint<id>> modint<id>::invs = {0}; using modint998244353 = modint<998244353>; using modint1000000007 = modint<1000000007>; namespace internal { template<class T> struct is_modint : public std::false_type {}; template<int id> struct is_modint<modint<id>> : public std::true_type {}; template<class T, class ENABLE = void> struct is_static_modint : public std::false_type {}; template<int id> struct is_static_modint<modint<id>, std::enable_if_t<(id > 0)>> : public std::true_type {}; template<class T> using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>; template<class T, class ENABLE = void> struct is_dynamic_modint : public std::false_type {}; template<int id> struct is_dynamic_modint<modint<id>, std::enable_if_t<(id <= 0)>> : public std::true_type {}; template<class T> using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>; } // namespace internal } // namespace felix #line 2 "library/bst/rbst-base.hpp" #include <tuple> #include <functional> #line 2 "library/random/rng.hpp" #include <chrono> namespace felix { inline unsigned long long rng() { static unsigned long long SEED = std::chrono::steady_clock::now().time_since_epoch().count(); SEED ^= SEED << 7; SEED ^= SEED >> 9; return SEED; } } // namespace felix #line 5 "library/bst/rbst-base.hpp" namespace felix { namespace internal { template<class node_t, class Comp = std::less<decltype(node_t::key)>> struct rbst_base { using key_type = decltype(node_t::key); private: static const Comp Compare; public: static node_t* merge(node_t* a, node_t* b) { if(a == nullptr || b == nullptr) { return a != nullptr ? a : b; } if((int) (((unsigned int) rng() * 1LL * (a->size + b->size)) >> 32) < a->size) { a->push(); a->r = merge(a->r, b); a->pull(); return a; } else { b->push(); b->l = merge(a, b->l); b->pull(); return b; } } static std::pair<node_t*, node_t*> split(node_t* v, int k) { if(v == nullptr) { return {nullptr, nullptr}; } v->push(); if(k <= get_size(v->l)) { auto p = split(v->l, k); v->l = p.second; if(p.first != nullptr) { p.first->p = nullptr; } v->pull(); return {p.first, v}; } else { auto p = split(v->r, k - get_size(v->l) - 1); v->r = p.first; if(p.second != nullptr) { p.second->p = nullptr; } v->pull(); return {v, p.second}; } } static std::tuple<node_t*, node_t*, node_t*> split_range(node_t* v, int l, int r) { auto p = split(v, l); auto q = split(p.second, r - l); return {p.first, q.first, q.second}; } static void insert(node_t*& v, int k, const key_type& val) { auto p = split(v, k); v = merge(p.first, merge(new node_t(val), p.second)); } static void erase(node_t*& v, int k) { auto p = split_range(v, k, k + 1); delete std::get<1>(p); v = merge(std::get<0>(p), std::get<2>(p)); } static int lower_bound(node_t* v, const key_type& val) { if(v == nullptr) { return 0; } // TTTTFFFF // ^ if(Compare(v->key, val)) { return get_size(v->l) + 1 + lower_bound(v->r, val); } else { return lower_bound(v->l, val); } } static int upper_bound(node_t* v, const key_type& val) { // 1 2 3 3 4 // ^ // F F F F T if(v == nullptr) { return 0; } if(!Compare(val, v->key)) { return get_size(v->l) + 1 + upper_bound(v->r, val); } else { return upper_bound(v->l, val); } } static key_type get(node_t*& v, int k) { auto p = split_range(v, k, k + 1); key_type res = std::get<1>(p)->key; v = merge(std::get<0>(p), merge(std::get<1>(p), std::get<2>(p))); return res; } static int get_index(node_t* v) { int k = get_size(v->l); while(v->p != nullptr) { if(v == v->p->r) { k++; if(v->p->l != nullptr) { k += v->p->l->size; } } v = v->p; } return k; } static void clear(node_t*& v) { postorder(v, [](node_t* v) { delete v; }); v = nullptr; } static node_t* next(node_t* v) { if(v->r == nullptr) { while(v->p != nullptr && v->p->r == v) { v = v->p; } return v->p; } v->push(); if(v->r == nullptr) { return nullptr; } v = v->r; while(v->l != nullptr) { v->push(); v = v->l; } return v; } static node_t* prev(node_t* v) { if(v->l == nullptr) { while(v->p != nullptr && v->p->l == v) { v = v->p; } return v->p; } v->push(); if(v->l == nullptr) { return nullptr; } v = v->l; while(v->r != nullptr) { v->push(); v = v->r; } return v; } template<class Func> static void preorder(node_t* v, const Func& f) { auto rec = [&](auto rec, node_t* v) -> void { if(v == nullptr) { return; } v->push(); f(v); rec(rec, v->l); rec(rec, v->r); }; rec(rec, v); } template<class Func> static void inorder(node_t* v, const Func& f) { auto rec = [&](auto rec, node_t* v) -> void { if(v == nullptr) { return; } v->push(); rec(rec, v->l); f(v); rec(rec, v->r); }; rec(rec, v); } template<class Func> static void postorder(node_t* v, const Func& f) { auto rec = [&](auto rec, node_t* v) -> void { if(v == nullptr) { return; } v->push(); rec(rec, v->l); rec(rec, v->r); f(v); }; rec(rec, v); } static int size(node_t* v) { return get_size(v); } static bool empty(node_t* v) { return v == nullptr; } private: static int get_size(node_t* v) { return v != nullptr ? v->size : 0; } }; template<class node_t, class Comp> const Comp rbst_base<node_t, Comp>::Compare = Comp(); } // namespace internal } // namespace felix #line 3 "library/data-structure/treap.hpp" namespace felix { namespace internal_treap { template<class S, S (*e)(), S (*op)(S, S)> struct treap_node { S key = e(), sum = e(); int size = 1; treap_node* l = nullptr; treap_node* r = nullptr; treap_node* p = nullptr; treap_node() {} treap_node(const S& s) : key(s), sum(s) {} void push() {} void pull() { size = 1; sum = key; if(l != nullptr) { size += l->size; sum = op(l->sum, sum); l->p = this; } if(r != nullptr) { size += r->size; sum = op(sum, r->sum); r->p = this; } } }; } // namespace internal_treap template<class S, S (*e)(), S (*op)(S, S), class Comp = std::less<S>> struct treap : public internal::rbst_base<internal_treap::treap_node<S, e, op>, Comp> { using node_t = internal_treap::treap_node<S, e, op>; using base = internal::rbst_base<internal_treap::treap_node<S, e, op>, Comp>; using base::split_range_by_size, base::merge; using base::root; public: treap() {} void set(int k, const S& s) { auto [lhs, mid, rhs] = split_range_by_size(k, k + 1); mid.clear(); mid.insert(mid.end(), s); merge(lhs), merge(mid), merge(rhs); } S prod(int l, int r) { if(l == r) { return e(); } auto [lhs, mid, rhs] = split_range_by_size(l, r); S ans = mid.root->sum; merge(lhs), merge(mid), merge(rhs); return ans; } S all_prod() { root->push(); return root->sum; } }; } // namespace felix #line 7 "test/data-structure/treap/yosupo-Dynamic-Sequence-Range-Affine-Range-Sum.test.cpp" using namespace std; using namespace felix; using mint = modint998244353; struct S { mint sum; int sz = 0; S() {} S(mint x, int y = 1) : sum(x), sz(y) {} }; S e() { return S(); } S op(S a, S b) { return S(a.sum + b.sum, a.sz + b.sz); } S reversal(S s) { return s; } struct F { mint a = 1, b = 0; F() {} F(mint x, mint y) : a(x), b(y) {} bool operator!=(const F& other) const { return a != other.a || b != other.b; } }; F id() { return F(); } S mapping(F f, S s) { s.sum = f.a * s.sum + f.b * s.sz; return s; } F composition(F a, F b) { return F(a.a * b.a, a.a * b.b + a.b); } int main() { ios::sync_with_stdio(false); cin.tie(0); int n, q; cin >> n >> q; treap<S, e, op, reversal, F, id, mapping, composition> tree; for(int i = 0; i < n; i++) { mint x; cin >> x; tree.insert(tree.end(), S(x)); } while(q--) { int type; cin >> type; if(type == 0) { int p, x; cin >> p >> x; tree.insert_k(p, S(x)); } else if(type == 1) { int p; cin >> p; tree.erase_k(p); } else if(type == 2) { int l, r; cin >> l >> r; tree.reverse(l, r); } else if(type == 3) { int l, r, a, b; cin >> l >> r >> a >> b; tree.apply(l, r, F(a, b)); } else { int l, r; cin >> l >> r; cout << tree.prod(l, r).sum << "\n"; } } return 0; }