This documentation is automatically generated by competitive-verifier/competitive-verifier
// @brief Range Affine Range Sum
#define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum"
#include "cp-algo/structures/segtree/metas/affine.hpp"
#include "cp-algo/structures/segtree.hpp"
#include "cp-algo/number_theory/modint.hpp"
#include <bits/stdc++.h>
using namespace std;
using namespace cp_algo::structures;
using base = cp_algo::math::modint<998244353>;
using meta = segtree::metas::affine_meta<base>;
void solve() {
int n, q;
cin >> n >> q;
vector<meta> a(n);
for(int i = 0; i < n; i++) {
int ai;
cin >> ai;
a[i] = {ai};
}
segtree_t<meta> me(a);
while(q--) {
int t;
cin >> t;
if(t == 0) {
int l, r, b, c;
cin >> l >> r >> b >> c;
me.exec_on_segment(l, r, [&](auto& meta) {
meta.to_push.prepend(meta::lin(b, c));
});
} else {
int l, r;
cin >> l >> r;
base ans = 0;
me.exec_on_segment(l, r, [&](auto meta) {
ans += meta.sum;
});
cout << ans << "\n";
}
}
}
signed main() {
//freopen("input.txt", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(0);
int t = 1;
while(t--) {
solve();
}
}
#line 1 "verify/structures/segtree/range_affine_range_sum.test.cpp"
// @brief Range Affine Range Sum
#define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum"
#line 1 "cp-algo/structures/segtree/metas/affine.hpp"
#line 1 "cp-algo/structures/segtree/metas/base.hpp"
#include <cstddef>
namespace cp_algo::structures::segtree::metas {
template<typename derived_meta>
struct base_meta {
using meta = derived_meta;
virtual void pull(meta const&, meta const&, size_t, size_t) {};
virtual void push(meta*, meta*, size_t, size_t) {};
};
}
#line 1 "cp-algo/math/affine.hpp"
#include <optional>
#include <utility>
#include <cassert>
#include <tuple>
namespace cp_algo::math {
// a * x + b
template<typename base>
struct lin {
base a = 1, b = 0;
std::optional<base> c;
lin() {}
lin(base b): a(0), b(b) {}
lin(base a, base b): a(a), b(b) {}
lin(base a, base b, base _c): a(a), b(b), c(_c) {}
// polynomial product modulo x^2 - c
lin operator * (const lin& t) {
assert(c && t.c && *c == *t.c);
return {a * t.b + b * t.a, b * t.b + a * t.a * (*c), *c};
}
// a * (t.a * x + t.b) + b
lin apply(lin const& t) const {
return {a * t.a, a * t.b + b};
}
void prepend(lin const& t) {
*this = t.apply(*this);
}
base eval(base x) const {
return a * x + b;
}
};
// (ax+b) / (cx+d)
template<typename base>
struct linfrac {
base a, b, c, d;
linfrac(): a(1), b(0), c(0), d(1) {} // x, identity for composition
linfrac(base a): a(a), b(1), c(1), d(0) {} // a + 1/x, for continued fractions
linfrac(base a, base b, base c, base d): a(a), b(b), c(c), d(d) {}
// composition of two linfracs
linfrac operator * (linfrac t) const {
return t.prepend(linfrac(*this));
}
linfrac operator-() const {
return {-a, -b, -c, -d};
}
linfrac adj() const {
return {d, -b, -c, a};
}
linfrac& prepend(linfrac const& t) {
t.apply(a, c);
t.apply(b, d);
return *this;
}
// apply linfrac to A/B
void apply(base &A, base &B) const {
std::tie(A, B) = std::pair{a * A + b * B, c * A + d * B};
}
};
}
#line 5 "cp-algo/structures/segtree/metas/affine.hpp"
namespace cp_algo::structures::segtree::metas {
template<typename base>
struct affine_meta: base_meta<affine_meta<base>> {
using meta = affine_meta;
using lin = math::lin<base>;
base sum = 0;
lin to_push = {};
affine_meta() {}
affine_meta(base sum): sum(sum) {}
void push(meta *L, meta *R, size_t l, size_t r) override {
if(to_push.a != 1 || to_push.b != 0) {
sum = to_push.a * sum + to_push.b * (r - l);
if(r - l > 1) {
L->to_push.prepend(to_push);
R->to_push.prepend(to_push);
}
to_push = {};
}
}
void pull(meta const& L, meta const& R, size_t, size_t) override {
sum = L.sum + R.sum;
}
};
}
#line 1 "cp-algo/structures/segtree.hpp"
#include <vector>
#include <numeric>
namespace cp_algo::structures {
template<typename meta>
struct segtree_t {
const size_t N;
std::vector<meta> _meta;
segtree_t(size_t n): N(n), _meta(4 * N) {}
segtree_t(std::vector<meta> leafs): N(size(leafs)), _meta(4 * N) {
build(leafs);
}
void pull(size_t v, size_t l, size_t r) {
if(r - l > 1) {
_meta[v].pull(_meta[2 * v], _meta[2 * v + 1], l, r);
}
}
void push(size_t v, size_t l, size_t r) {
if(r - l > 1) {
_meta[v].push(&_meta[2 * v], &_meta[2 * v + 1], l, r);
} else {
_meta[v].push(nullptr, nullptr, l, r);
}
}
void build(auto &a, size_t v, size_t l, size_t r) {
if(r - l == 1) {
if(l < size(a)) {
_meta[v] = a[l];
}
} else {
size_t m = std::midpoint(l, r);
build(a, 2 * v, l, m);
build(a, 2 * v + 1, m, r);
pull(v, l, r);
}
}
void build(auto &a) {
build(a, 1, 0, N);
}
void exec_on_segment(size_t a, size_t b, auto func, auto proceed, auto stop, size_t v, size_t l, size_t r) {
push(v, l, r);
if(r <= a || b <= l || stop(_meta[v])) {
return;
} else if(a <= l && r <= b && proceed(_meta[v])) {
func(_meta[v]);
push(v, l, r);
} else {
size_t m = std::midpoint(l, r);
exec_on_segment(a, b, func, proceed, stop, 2 * v, l, m);
exec_on_segment(a, b, func, proceed, stop, 2 * v + 1, m, r);
pull(v, l, r);
}
}
static constexpr auto default_true = [](auto const&){return true;};
static constexpr auto default_false = [](auto const&){return false;};
void exec_on_segment(size_t a, size_t b, auto func, auto proceed, auto stop) {
exec_on_segment(a, b, func, proceed, stop, 1, 0, N);
}
void exec_on_segment(size_t a, size_t b, auto func) {
exec_on_segment(a, b, func, default_true, default_false);
}
};
}
#line 1 "cp-algo/number_theory/modint.hpp"
#line 1 "cp-algo/math/common.hpp"
#include <functional>
#include <cstdint>
namespace cp_algo::math {
#ifdef CP_ALGO_MAXN
const int maxn = CP_ALGO_MAXN;
#else
const int maxn = 1 << 19;
#endif
const int magic = 64; // threshold for sizes to run the naive algo
auto bpow(auto const& x, auto n, auto const& one, auto op) {
if(n == 0) {
return one;
} else {
auto t = bpow(x, n / 2, one, op);
t = op(t, t);
if(n % 2) {
t = op(t, x);
}
return t;
}
}
auto bpow(auto x, auto n, auto ans) {
return bpow(x, n, ans, std::multiplies{});
}
template<typename T>
T bpow(T const& x, auto n) {
return bpow(x, n, T(1));
}
}
#line 4 "cp-algo/number_theory/modint.hpp"
#include <iostream>
#line 6 "cp-algo/number_theory/modint.hpp"
namespace cp_algo::math {
inline constexpr auto inv2(auto x) {
assert(x % 2);
std::make_unsigned_t<decltype(x)> y = 1;
while(y * x != 1) {
y *= 2 - x * y;
}
return y;
}
template<typename modint, typename _Int>
struct modint_base {
using Int = _Int;
using UInt = std::make_unsigned_t<Int>;
static constexpr size_t bits = sizeof(Int) * 8;
using Int2 = std::conditional_t<bits <= 32, int64_t, __int128_t>;
using UInt2 = std::conditional_t<bits <= 32, uint64_t, __uint128_t>;
static Int mod() {
return modint::mod();
}
static UInt imod() {
return modint::imod();
}
static UInt2 pw128() {
return modint::pw128();
}
static UInt m_reduce(UInt2 ab) {
if(mod() % 2 == 0) [[unlikely]] {
return UInt(ab % mod());
} else {
UInt2 m = (UInt)ab * imod();
return UInt((ab + m * mod()) >> bits);
}
}
static UInt m_transform(UInt a) {
if(mod() % 2 == 0) [[unlikely]] {
return a;
} else {
return m_reduce(a * pw128());
}
}
modint_base(): r(0) {}
modint_base(Int2 rr): r(UInt(rr % mod())) {
r = std::min(r, r + mod());
r = m_transform(r);
}
modint inv() const {
return bpow(to_modint(), mod() - 2);
}
modint operator - () const {
modint neg;
neg.r = std::min(-r, 2 * mod() - r);
return neg;
}
modint& operator /= (const modint &t) {
return to_modint() *= t.inv();
}
modint& operator *= (const modint &t) {
r = m_reduce((UInt2)r * t.r);
return to_modint();
}
modint& operator += (const modint &t) {
r += t.r; r = std::min(r, r - 2 * mod());
return to_modint();
}
modint& operator -= (const modint &t) {
r -= t.r; r = std::min(r, r + 2 * mod());
return to_modint();
}
modint operator + (const modint &t) const {return modint(to_modint()) += t;}
modint operator - (const modint &t) const {return modint(to_modint()) -= t;}
modint operator * (const modint &t) const {return modint(to_modint()) *= t;}
modint operator / (const modint &t) const {return modint(to_modint()) /= t;}
// Why <=> doesn't work?..
auto operator == (const modint_base &t) const {return getr() == t.getr();}
auto operator != (const modint_base &t) const {return getr() != t.getr();}
auto operator <= (const modint_base &t) const {return getr() <= t.getr();}
auto operator >= (const modint_base &t) const {return getr() >= t.getr();}
auto operator < (const modint_base &t) const {return getr() < t.getr();}
auto operator > (const modint_base &t) const {return getr() > t.getr();}
Int rem() const {
UInt R = getr();
return 2 * R > (UInt)mod() ? R - mod() : R;
}
// Only use if you really know what you're doing!
UInt modmod() const {return (UInt)8 * mod() * mod();};
void add_unsafe(UInt t) {r += t;}
void pseudonormalize() {r = std::min(r, r - modmod());}
modint const& normalize() {
if(r >= (UInt)mod()) {
r %= mod();
}
return to_modint();
}
void setr(UInt rr) {r = m_transform(rr);}
UInt getr() const {
UInt res = m_reduce(r);
return std::min(res, res - mod());
}
void setr_direct(UInt rr) {r = rr;}
UInt getr_direct() const {return r;}
private:
UInt r;
modint& to_modint() {return static_cast<modint&>(*this);}
modint const& to_modint() const {return static_cast<modint const&>(*this);}
};
template<typename modint>
concept modint_type = std::is_base_of_v<modint_base<modint, typename modint::Int>, modint>;
template<modint_type modint>
std::istream& operator >> (std::istream &in, modint &x) {
typename modint::UInt r;
auto &res = in >> r;
x.setr(r);
return res;
}
template<modint_type modint>
std::ostream& operator << (std::ostream &out, modint const& x) {
return out << x.getr();
}
template<auto m>
struct modint: modint_base<modint<m>, decltype(m)> {
using Base = modint_base<modint<m>, decltype(m)>;
using Base::Base;
static constexpr Base::UInt im = m % 2 ? inv2(-m) : 0;
static constexpr Base::UInt r2 = (typename Base::UInt2)(-1) % m + 1;
static constexpr Base::Int mod() {return m;}
static constexpr Base::UInt imod() {return im;}
static constexpr Base::UInt2 pw128() {return r2;}
};
template<typename Int = int64_t>
struct dynamic_modint: modint_base<dynamic_modint<Int>, Int> {
using Base = modint_base<dynamic_modint<Int>, Int>;
using Base::Base;
static Int mod() {return m;}
static Base::UInt imod() {return im;}
static Base::UInt2 pw128() {return r2;}
static void switch_mod(Int nm) {
m = nm;
im = m % 2 ? inv2(-m) : 0;
r2 = static_cast<Base::UInt>(static_cast<Base::UInt2>(-1) % m + 1);
}
// Wrapper for temp switching
auto static with_mod(Int tmp, auto callback) {
struct scoped {
Int prev = mod();
~scoped() {switch_mod(prev);}
} _;
switch_mod(tmp);
return callback();
}
private:
static thread_local Int m;
static thread_local Base::UInt im, r2;
};
template<typename Int>
Int thread_local dynamic_modint<Int>::m = 1;
template<typename Int>
dynamic_modint<Int>::Base::UInt thread_local dynamic_modint<Int>::im = -1;
template<typename Int>
dynamic_modint<Int>::Base::UInt thread_local dynamic_modint<Int>::r2 = 0;
}
#line 6 "verify/structures/segtree/range_affine_range_sum.test.cpp"
#include <bits/stdc++.h>
using namespace std;
using namespace cp_algo::structures;
using base = cp_algo::math::modint<998244353>;
using meta = segtree::metas::affine_meta<base>;
void solve() {
int n, q;
cin >> n >> q;
vector<meta> a(n);
for(int i = 0; i < n; i++) {
int ai;
cin >> ai;
a[i] = {ai};
}
segtree_t<meta> me(a);
while(q--) {
int t;
cin >> t;
if(t == 0) {
int l, r, b, c;
cin >> l >> r >> b >> c;
me.exec_on_segment(l, r, [&](auto& meta) {
meta.to_push.prepend(meta::lin(b, c));
});
} else {
int l, r;
cin >> l >> r;
base ans = 0;
me.exec_on_segment(l, r, [&](auto meta) {
ans += meta.sum;
});
cout << ans << "\n";
}
}
}
signed main() {
//freopen("input.txt", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(0);
int t = 1;
while(t--) {
solve();
}
}
Env | Name | Status | Elapsed | Memory |
---|---|---|---|---|
g++ | example_00 | AC | 5 ms | 4 MB |
g++ | max_random_00 | AC | 974 ms | 97 MB |
g++ | max_random_01 | AC | 944 ms | 97 MB |
g++ | max_random_02 | AC | 971 ms | 97 MB |
g++ | random_00 | AC | 727 ms | 76 MB |
g++ | random_01 | AC | 743 ms | 90 MB |
g++ | random_02 | AC | 490 ms | 13 MB |
g++ | small_00 | AC | 6 ms | 4 MB |
g++ | small_01 | AC | 5 ms | 4 MB |
g++ | small_02 | AC | 5 ms | 4 MB |
g++ | small_03 | AC | 5 ms | 4 MB |
g++ | small_04 | AC | 5 ms | 4 MB |
g++ | small_05 | AC | 5 ms | 4 MB |
g++ | small_06 | AC | 5 ms | 4 MB |
g++ | small_07 | AC | 5 ms | 4 MB |
g++ | small_08 | AC | 5 ms | 4 MB |
g++ | small_09 | AC | 5 ms | 4 MB |
g++ | small_random_00 | AC | 5 ms | 4 MB |
g++ | small_random_01 | AC | 5 ms | 4 MB |