This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/range_set_range_composite"
#include <bits/stdc++.h>
using namespace std;
#include "../../../lib/math/modint.hpp"
#include "../../../lib/data_structure/lazy_segment_tree.hpp"
using mint = ModInt<998244353>;
struct S{
mint a, b;
long long size;
};
struct F{
mint a, b;
bool id = false;
};
F ID = {1, 0, true};
S op(S l, S r){
return{l.a * r.a, r.a * l.b + r.b, l.size + r.size};
}
S e(){
return S{1, 0};
}
S mapping(F f, S x){
if(f.id){
return x;
}
auto spow = [](S a, long long n){
S ret = {1, 0, 0};
while(n > 0){
if(n & 1) ret = op(ret, a);
a = op(a, a);
n >>= 1;
}
return ret;
};
S pr = spow(S{f.a, f.b, 0}, x.size);
return S{pr.a, pr.b, x.size};
}
F composition(F f, F g){
if(f.id){
return g;
}
return f;
}
F id(){
return ID;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
vector<S> p(n);
for(int i = 0; i < n; i++){
int a, b;
cin >> a >> b;
p[i] = S{a, b, 1};
}
LazySegTree<S, op, e, F, mapping, composition, id> seg(p);
while(q--){
int t;
cin >> t;
if(t == 0){
int l, r, c, d;
cin >> l >> r >> c >> d;
seg.apply(l, r, F{c, d, false});
} else{
int l, r;
mint x;
cin >> l >> r >> x;
S pr = seg.query(l, r);
cout << pr.a * x + pr.b << "\n";
}
}
}
#line 1 "test/library_checker/data_structure/range_set_range_composite.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/range_set_range_composite"
#include <bits/stdc++.h>
using namespace std;
#line 2 "lib/math/modint.hpp"
#line 5 "lib/math/modint.hpp"
/**
* @brief ModInt
* @docs docs/math/modint.md
*/
template <long long Modulus>
struct ModInt{
long long val;
static constexpr int mod() { return Modulus; }
constexpr ModInt(const long long _val = 0) noexcept : val(_val) {
normalize();
}
void normalize(){
val = (val % Modulus + Modulus) % Modulus;
}
inline ModInt &operator+=(const ModInt &rhs) noexcept {
if(val += rhs.val, val >= Modulus) val -= Modulus;
return *this;
}
inline ModInt &operator-=(const ModInt &rhs) noexcept {
if(val -= rhs.val, val < 0) val += Modulus;
return *this;
}
inline ModInt &operator*=(const ModInt &rhs) noexcept {
val = val * rhs.val % Modulus;
return *this;
}
inline ModInt &operator/=(const ModInt &rhs) noexcept {
val = val * inv(rhs.val).val % Modulus;
return *this;
}
inline ModInt &operator++() noexcept {
if(++val >= Modulus) val -= Modulus;
return *this;
}
inline ModInt operator++(int) noexcept {
ModInt t = val;
if(++val >= Modulus) val -= Modulus;
return t;
}
inline ModInt &operator--() noexcept {
if(--val < 0) val += Modulus;
return *this;
}
inline ModInt operator--(int) noexcept {
ModInt t = val;
if(--val < 0) val += Modulus;
return t;
}
inline ModInt operator-() const noexcept { return (Modulus - val) % Modulus; }
inline ModInt inv(void) const { return inv(val); }
ModInt pow(long long n) const {
assert(0 <= n);
ModInt x = *this, r = 1;
while(n){
if(n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
ModInt inv(const long long n) const {
long long a = n, b = Modulus, u = 1, v = 0;
while(b){
long long t = a / b;
a -= t * b; std::swap(a, b);
u -= t * v; std::swap(u, v);
}
u %= Modulus;
if(u < 0) u += Modulus;
return u;
}
friend inline ModInt operator+(const ModInt &lhs, const ModInt &rhs) noexcept { return ModInt(lhs) += rhs; }
friend inline ModInt operator-(const ModInt &lhs, const ModInt &rhs) noexcept { return ModInt(lhs) -= rhs; }
friend inline ModInt operator*(const ModInt &lhs, const ModInt &rhs) noexcept { return ModInt(lhs) *= rhs; }
friend inline ModInt operator/(const ModInt &lhs, const ModInt &rhs) noexcept { return ModInt(lhs) /= rhs; }
friend inline bool operator==(const ModInt &lhs, const ModInt &rhs) noexcept { return lhs.val == rhs.val; }
friend inline bool operator!=(const ModInt &lhs, const ModInt &rhs) noexcept { return lhs.val != rhs.val; }
friend inline std::istream &operator>>(std::istream &is, ModInt &x) noexcept {
is >> x.val;
x.normalize();
return is;
}
friend inline std::ostream &operator<<(std::ostream &os, const ModInt &x) noexcept { return os << x.val; }
};
#line 2 "lib/data_structure/lazy_segment_tree.hpp"
template <class S,
S(*op)(S, S),
S(*e)(),
class F,
S(*mapping)(F, S),
F(*composition)(F, F),
F(*id)()>
struct LazySegTree{
private:
int _n, size, log;
vector<S> d;
vector<F> lz;
void pull(int k){ d[k] = op(d[2 * k], d[2 * k + 1]); }
void all_apply(int k, F f){
d[k] = mapping(f, d[k]);
if(k < size) lz[k] = composition(f, lz[k]);
}
void push(int k){
all_apply(2 * k, lz[k]);
all_apply(2 * k + 1, lz[k]);
lz[k] = id();
}
public:
LazySegTree() : LazySegTree(0){}
LazySegTree(int n) : LazySegTree(vector<S>(n, e())){}
LazySegTree(const vector<S> &v) : _n(int(v.size())){
log = 0;
size = 1;
while(size < _n) size <<= 1, log++;
d = vector<S>(2 * size, e());
lz = vector<F>(size, id());
for(int i = 0; i < _n; i++) d[size + i] = v[i];
for(int i = size - 1; i >= 1; i--){
pull(i);
}
}
void update(int p, S x){
assert(0 <= p && p < _n);
p += size;
for(int i = log; i >= 1; i--) push(p >> i);
d[p] = x;
for(int i = 1; i <= log; i++) pull(p >> i);
}
S get(int p){
assert(0 <= p && p < _n);
p += size;
for(int i = log; i >= 1; i--) push(p >> i);
return d[p];
}
S query(int l, int r){
assert(0 <= l && l <= r && r <= _n);
if(l == r) return e();
l += size;
r += size;
for(int i = log; i >= 1; i--){
if(((l >> i) << i) != l) push(l >> i);
if(((r >> i) << i) != r) push(r >> i);
}
S sml = e(), smr = e();
while(l < r){
if(l & 1) sml = op(sml, d[l++]);
if(r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_query(){ return d[1]; }
void apply(int p, F f){
assert(0 <= p && p < _n);
p += size;
for(int i = log; i >= 1; i--) push(p >> i);
d[p] = mapping(f, d[p]);
for(int i = 1; i <= log; i++) pull(p >> i);
}
void apply(int l, int r, F f){
assert(0 <= l && l <= r && r <= _n);
if(l == r) return;
l += size;
r += size;
for(int i = log; i >= 1; i--){
if(((l >> i) << i) != l) push(l >> i);
if(((r >> i) << i) != r) push((r - 1) >> i);
}
{
int l2 = l, r2 = r;
while(l < r){
if(l & 1) all_apply(l++, f);
if(r & 1) all_apply(--r, f);
l >>= 1;
r >>= 1;
}
l = l2;
r = r2;
}
for(int i = 1; i <= log; i++){
if(((l >> i) << i) != l) pull(l >> i);
if(((r >> i) << i) != r) pull((r - 1) >> i);
}
}
template <bool (*g)(S)>
int max_right(int l){
return max_right(l, [](S x){ return g(x); });
}
template <class G>
int max_right(int l, G g){
assert(0 <= l && l <= _n);
assert(g(e()));
if(l == _n) return _n;
l += size;
for(int i = log; i >= 1; i--) push(l >> i);
S sm = e();
do{
while(l % 2 == 0) l >>= 1;
if(!g(op(sm, d[l]))){
while(l < size){
push(l);
l = (2 * l);
if(g(op(sm, d[l]))){
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while((l & -l) != l);
return _n;
}
template <bool (*g)(S)>
int min_left(int r){
return min_left(r, [](S x){ return g(x); });
}
template <class G>
int min_left(int r, G g){
assert(0 <= r && r <= _n);
assert(g(e()));
if(r == 0) return 0;
r += size;
for(int i = log; i >= 1; i--) push((r - 1) >> i);
S sm = e();
do{
r--;
while(r > 1 && (r % 2)) r >>= 1;
if(!g(op(d[r], sm))){
while(r < size){
push(r);
r = (2 * r + 1);
if(g(op(d[r], sm))){
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while((r & -r) != r);
return 0;
}
};
#line 7 "test/library_checker/data_structure/range_set_range_composite.test.cpp"
using mint = ModInt<998244353>;
struct S{
mint a, b;
long long size;
};
struct F{
mint a, b;
bool id = false;
};
F ID = {1, 0, true};
S op(S l, S r){
return{l.a * r.a, r.a * l.b + r.b, l.size + r.size};
}
S e(){
return S{1, 0};
}
S mapping(F f, S x){
if(f.id){
return x;
}
auto spow = [](S a, long long n){
S ret = {1, 0, 0};
while(n > 0){
if(n & 1) ret = op(ret, a);
a = op(a, a);
n >>= 1;
}
return ret;
};
S pr = spow(S{f.a, f.b, 0}, x.size);
return S{pr.a, pr.b, x.size};
}
F composition(F f, F g){
if(f.id){
return g;
}
return f;
}
F id(){
return ID;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
vector<S> p(n);
for(int i = 0; i < n; i++){
int a, b;
cin >> a >> b;
p[i] = S{a, b, 1};
}
LazySegTree<S, op, e, F, mapping, composition, id> seg(p);
while(q--){
int t;
cin >> t;
if(t == 0){
int l, r, c, d;
cin >> l >> r >> c >> d;
seg.apply(l, r, F{c, d, false});
} else{
int l, r;
mint x;
cin >> l >> r >> x;
S pr = seg.query(l, r);
cout << pr.a * x + pr.b << "\n";
}
}
}