This documentation is automatically generated by online-judge-tools/verification-helper
#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;
}