This documentation is automatically generated by competitive-verifier/competitive-verifier
// @brief Dynamic Range Affine Range Sum
#define PROBLEM "https://judge.yosupo.jp/problem/dynamic_sequence_range_affine_range_sum"
#include "cp-algo/number_theory/modint.hpp"
#include "cp-algo/data_structures/treap/metas/reverse.hpp"
#include "cp-algo/data_structures/treap.hpp"
#include <bits/stdc++.h>
using namespace std;
using namespace cp_algo::data_structures::treap;
using base = cp_algo::math::modint<998244353>;
using meta = metas::reverse_meta<base>;
using node_t = node<meta>;
using treap = node_t::treap;
void solve() {
istream_iterator<int> input(cin);
int n = *input++;
int q = *input++;
vector<treap> nodes(n);
generate_n(begin(nodes), n, [&](){
return node_t::make_treap(meta(*input++));
});
auto me = node_t::build(nodes);
while(q--) {
int t = *input++;
if(t == 0) {
int i = *input++;
base x = *input++;
node_t::insert(me, i, node_t::make_treap(meta(x)));
} else if(t == 1) {
node_t::erase(me, *input++);
} else if(t == 2) {
int l = *input++;
int r = *input++;
node_t::exec_on_segment(me, l, r, [](auto &t) {
_safe_meta(t, reverse = 1);
});
} else if(t == 3) {
int l = *input++;
int r = *input++;
base b = *input++;
base c = *input++;
node_t::exec_on_segment(me, l, r, [b, c](auto &t) {
_safe_meta(t, add_push(meta::lin(b, c)));
});
} else {
int l = *input++;
int r = *input++;
node_t::exec_on_segment(me, l, r, [](auto t) {
cout << _safe_meta(t, sum) << "\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/data_structures/treap/dynamic_sequence_range_affine_range_sum.test.cpp"
// @brief Dynamic Range Affine Range Sum
#define PROBLEM "https://judge.yosupo.jp/problem/dynamic_sequence_range_affine_range_sum"
#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>
#include <cassert>
namespace cp_algo::math {
inline constexpr uint64_t inv64(uint64_t x) {
assert(x % 2);
uint64_t y = 1;
while(y * x != 1) {
y *= 2 - x * y;
}
return y;
}
template<typename modint>
struct modint_base {
static int64_t mod() {
return modint::mod();
}
static uint64_t imod() {
return modint::imod();
}
static __uint128_t pw128() {
return modint::pw128();
}
static uint64_t m_reduce(__uint128_t ab) {
if(mod() % 2 == 0) [[unlikely]] {
return ab % mod();
} else {
uint64_t m = ab * imod();
return (ab + __uint128_t(m) * mod()) >> 64;
}
}
static uint64_t m_transform(uint64_t a) {
if(mod() % 2 == 0) [[unlikely]] {
return a;
} else {
return m_reduce(a * pw128());
}
}
modint_base(): r(0) {}
modint_base(int64_t rr): r(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(__uint128_t(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();}
int64_t rem() const {
uint64_t R = getr();
return 2 * R > (uint64_t)mod() ? R - mod() : R;
}
// Only use if you really know what you're doing!
uint64_t modmod() const {return 8ULL * mod() * mod();};
void add_unsafe(uint64_t t) {r += t;}
void pseudonormalize() {r = std::min(r, r - modmod());}
modint const& normalize() {
if(r >= (uint64_t)mod()) {
r %= mod();
}
return to_modint();
}
void setr(uint64_t rr) {r = m_transform(rr);}
uint64_t getr() const {
uint64_t res = m_reduce(r);
return std::min(res, res - mod());
}
void setr_direct(uint64_t rr) {r = rr;}
uint64_t getr_direct() const {return std::min(r, r - mod());}
private:
uint64_t r;
modint& to_modint() {return static_cast<modint&>(*this);}
modint const& to_modint() const {return static_cast<modint const&>(*this);}
};
template<typename modint>
std::istream& operator >> (std::istream &in, modint_base<modint> &x) {
uint64_t r;
auto &res = in >> r;
x.setr(r);
return res;
}
template<typename modint>
std::ostream& operator << (std::ostream &out, modint_base<modint> const& x) {
return out << x.getr();
}
template<typename modint>
concept modint_type = std::is_base_of_v<modint_base<modint>, modint>;
template<int64_t m>
struct modint: modint_base<modint<m>> {
static constexpr uint64_t im = m % 2 ? inv64(-m) : 0;
static constexpr uint64_t r2 = __uint128_t(-1) % m + 1;
static constexpr int64_t mod() {return m;}
static constexpr uint64_t imod() {return im;}
static constexpr __uint128_t pw128() {return r2;}
using Base = modint_base<modint<m>>;
using Base::Base;
};
struct dynamic_modint: modint_base<dynamic_modint> {
static int64_t mod() {return m;}
static uint64_t imod() {return im;}
static __uint128_t pw128() {return r2;}
static void switch_mod(int64_t nm) {
m = nm;
im = m % 2 ? inv64(-m) : 0;
r2 = __uint128_t(-1) % m + 1;
}
using Base = modint_base<dynamic_modint>;
using Base::Base;
// Wrapper for temp switching
auto static with_mod(int64_t tmp, auto callback) {
struct scoped {
int64_t prev = mod();
~scoped() {switch_mod(prev);}
} _;
switch_mod(tmp);
return callback();
}
private:
static int64_t m;
static uint64_t im, r1, r2;
};
int64_t dynamic_modint::m = 1;
uint64_t dynamic_modint::im = -1;
uint64_t dynamic_modint::r2 = 0;
}
#line 1 "cp-algo/data_structures/treap/metas/reverse.hpp"
#line 1 "cp-algo/data_structures/treap/metas/base.hpp"
#line 1 "cp-algo/data_structures/treap/common.hpp"
#define _safe(t, op) (t ? t->op : typename std::remove_reference_t<decltype(t->op)>())
#line 5 "cp-algo/data_structures/treap/metas/base.hpp"
#include <algorithm>
#line 7 "cp-algo/data_structures/treap/metas/base.hpp"
#define _safe_meta(i, op) _safe(i, _meta.op)
namespace cp_algo::data_structures::treap::metas {
struct base_meta {
void pull(auto const, auto const){}
void push(auto&, auto&){}
};
}
#line 1 "cp-algo/math/affine.hpp"
#include <optional>
#include <utility>
#line 6 "cp-algo/math/affine.hpp"
#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 6 "cp-algo/data_structures/treap/metas/reverse.hpp"
namespace cp_algo::data_structures::treap::metas {
template<typename base>
struct reverse_meta: base_meta {
using lin = math::lin<base>;
base val;
size_t sz = 1;
bool reverse = false;
base sum = val;
lin to_push = {};
reverse_meta(base val): val(val) {}
void pull(auto const L, auto const R) {
sum = val + _safe_meta(L, sum) + _safe_meta(R, sum);
sz = 1 + _safe_meta(L, sz) + _safe_meta(R, sz);
}
void add_push(lin const& t) {
val = t.eval(val);
sum = t.a * sum + t.b * sz;
to_push.prepend(t);
}
void push(auto &L, auto &R) {
if(reverse) {
reverse = false;
std::swap(L, R);
_safe_meta(L, reverse ^= 1);
_safe_meta(R, reverse ^= 1);
}
if(to_push.a != 1 || to_push.b != 0) {
_safe_meta(L, add_push(to_push));
_safe_meta(R, add_push(to_push));
to_push = {};
}
}
};
}
#line 1 "cp-algo/data_structures/treap.hpp"
#line 1 "cp-algo/random/rng.hpp"
#include <chrono>
#include <random>
namespace cp_algo::random {
uint64_t rng() {
static std::mt19937_64 rng(
std::chrono::steady_clock::now().time_since_epoch().count()
);
return rng();
}
}
#line 5 "cp-algo/data_structures/treap.hpp"
#include <array>
namespace cp_algo::data_structures::treap {
template<typename meta>
struct node {
using treap = node*;
meta _meta;
int prior = random::rng();
size_t size = 1;
treap children[2] = {nullptr, nullptr};
enum subtree {L, R};
node() {}
node(meta _meta): _meta(_meta) {}
node(meta _meta, int prior): _meta(_meta), prior(prior) {}
static treap make_treap(auto...args) {
return new node(args...);
}
treap pull() {
_meta.pull(children[L], children[R]);
size = 1 + _safe(children[L], size) + _safe(children[R], size);
return this;
}
treap push() {
_meta.push(children[L], children[R]);
return this;
}
// set i-th child and pull metadata
treap set(subtree i, treap t) {
children[i] = t;
return pull();
}
// push changes and detach the i-th child
treap cut(subtree i) {
return children[i];
}
static treap merge(treap A, treap B) {
if(!_safe(A, push()) || !_safe(B, push())) {
return A ? A : B;
} else if(A->prior < B->prior) {
return A->set(R, merge(A->cut(R), B));
} else {
return B->set(L, merge(A, B->cut(L)));
}
}
// return {L, R}, where |L|=k or L=A when |A| < k
static std::array<treap, 2> split(treap A, size_t k) {
if(!_safe(A, push())) {
return {nullptr, nullptr};
} else if(_safe(A->children[L], size) >= k) {
auto [split_L, split_R] = split(A->cut(L), k);
return {split_L, A->set(L, split_R)};
} else {
k -= _safe(A->children[L], size) + 1;
auto [split_L, split_R] = split(A->cut(R), k);
return {A->set(R, split_L), split_R};
}
}
static void exec_on_segment(treap &A, size_t l, size_t r, auto func) {
auto [LM, R] = split(A, r);
auto [L, M] = split(LM, l);
func(M);
A = merge(L, merge(M, R));
}
static void insert(treap &A, size_t pos, treap t) {
auto [L, R] = split(A, pos);
A = merge(L, merge(t, R));
}
static void erase(treap &A, size_t pos) {
auto [L, MR] = split(A, pos);
auto [M, R] = split(MR, 1);
delete M;
A = merge(L, R);
}
static void exec_on_each(treap &A, auto func) {
if(A) {
exec_on_each(A->children[L], func);
func(A);
exec_on_each(A->children[R], func);
}
}
treap pull_all() {
_safe(children[L], pull_all());
_safe(children[R], pull_all());
return pull();
}
treap push_all() {
push();
_safe(children[L], push_all());
_safe(children[R], push_all());
return this;
}
static treap build(auto const& nodes) {
std::vector<treap> st;
for(auto cur: nodes) {
while(st.size() >= 2 && st[st.size() - 2]->prior > cur->prior) {
st.pop_back();
}
if(!st.empty() && st.back()->prior > cur->prior) {
cur->set(L, st.back());
st.pop_back();
}
if(!st.empty() && st.back()->prior < cur->prior) {
st.back()->set(R, cur);
}
st.push_back(cur);
}
return st.empty() ? nullptr : st[0]->pull_all();
}
};
struct null_meta {
void pull(auto const, auto const) {}
void push(auto&, auto&) {}
};
}
#line 6 "verify/data_structures/treap/dynamic_sequence_range_affine_range_sum.test.cpp"
#include <bits/stdc++.h>
using namespace std;
using namespace cp_algo::data_structures::treap;
using base = cp_algo::math::modint<998244353>;
using meta = metas::reverse_meta<base>;
using node_t = node<meta>;
using treap = node_t::treap;
void solve() {
istream_iterator<int> input(cin);
int n = *input++;
int q = *input++;
vector<treap> nodes(n);
generate_n(begin(nodes), n, [&](){
return node_t::make_treap(meta(*input++));
});
auto me = node_t::build(nodes);
while(q--) {
int t = *input++;
if(t == 0) {
int i = *input++;
base x = *input++;
node_t::insert(me, i, node_t::make_treap(meta(x)));
} else if(t == 1) {
node_t::erase(me, *input++);
} else if(t == 2) {
int l = *input++;
int r = *input++;
node_t::exec_on_segment(me, l, r, [](auto &t) {
_safe_meta(t, reverse = 1);
});
} else if(t == 3) {
int l = *input++;
int r = *input++;
base b = *input++;
base c = *input++;
node_t::exec_on_segment(me, l, r, [b, c](auto &t) {
_safe_meta(t, add_push(meta::lin(b, c)));
});
} else {
int l = *input++;
int r = *input++;
node_t::exec_on_segment(me, l, r, [](auto t) {
cout << _safe_meta(t, sum) << "\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 | 6 ms | 3 MB |
g++ | extreme_insertion_00 | AC | 212 ms | 58 MB |
g++ | extreme_insertion_01 | AC | 282 ms | 58 MB |
g++ | extreme_insertion_02 | AC | 257 ms | 58 MB |
g++ | max_00 | AC | 1023 ms | 117 MB |
g++ | max_01 | AC | 715 ms | 62 MB |
g++ | max_02 | AC | 1519 ms | 62 MB |
g++ | max_03 | AC | 2068 ms | 62 MB |
g++ | max_04 | AC | 1318 ms | 62 MB |
g++ | random_00 | AC | 1182 ms | 49 MB |
g++ | random_01 | AC | 1315 ms | 58 MB |
g++ | random_02 | AC | 682 ms | 10 MB |
g++ | random_03 | AC | 154 ms | 54 MB |
g++ | random_04 | AC | 280 ms | 36 MB |
g++ | small_00 | AC | 6 ms | 4 MB |
g++ | small_01 | AC | 6 ms | 4 MB |
g++ | small_02 | AC | 6 ms | 3 MB |
g++ | small_03 | AC | 6 ms | 4 MB |
g++ | small_04 | AC | 6 ms | 4 MB |
g++ | small_05 | AC | 6 ms | 4 MB |
g++ | small_06 | AC | 6 ms | 4 MB |
g++ | small_07 | AC | 6 ms | 4 MB |
g++ | small_08 | AC | 6 ms | 4 MB |
g++ | small_09 | AC | 6 ms | 4 MB |
g++ | wrong_avl_killer_00 | AC | 337 ms | 58 MB |
g++ | wrong_avl_killer_01 | AC | 318 ms | 58 MB |