Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "bits/stdc++.h"
- using namespace std;
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- using namespace __gnu_pbds;
- template<class key, class cmp = std::less<key>>
- using op_set = tree<key, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>;
- #ifdef thunder
- #include "bug.h"
- #else
- #define bug(...)
- #endif
- #define ll long long
- #define lld double
- #define all(x) x.begin(), x.end()
- #define iceil(n, x) (((n) + (x) - 1) / (x))
- const ll INF=2e18;
- const ll mod=998244353;
- const ll maxn=1e5+5;
- template< ll mod >
- struct ModInt {
- ll x;
- ModInt() : x(0) {}
- ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
- ModInt &operator+=(const ModInt &p) {
- if((x += p.x) >= mod) x -= mod;
- return *this;
- }
- ModInt &operator-=(const ModInt &p) {
- if((x += mod - p.x) >= mod) x -= mod;
- return *this;
- }
- ModInt &operator*=(const ModInt &p) {
- x = (int) (1LL * x * p.x % mod);
- return *this;
- }
- ModInt &operator/=(const ModInt &p) {
- *this *= p.inverse();
- return *this;
- }
- ModInt operator-() const { return ModInt(-x); }
- ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
- ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
- ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
- ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
- bool operator<(const ModInt &p) const { return x < p.x; }
- bool operator>(const ModInt &p) const { return x > p.x; }
- bool operator==(const ModInt &p) const { return x == p.x; }
- bool operator!=(const ModInt &p) const { return x != p.x; }
- string to_str() { return to_string(x); }
- ModInt inverse() const {
- ll a = x, b = mod, u = 1, v = 0, t;
- while(b > 0) {
- t = a / b;
- swap(a -= t * b, b);
- swap(u -= t * v, v);
- }
- return ModInt(u);
- }
- ModInt pow(int64_t n) const {
- ModInt ret(1), mul(x);
- while(n > 0) {
- if(n & 1LL) ret *= mul;
- mul *= mul;
- n >>= 1LL;
- }
- return ret;
- }
- friend ostream &operator<<(ostream &os, const ModInt &p) {
- return os << p.x;
- }
- friend istream &operator>>(istream &is, ModInt &a) {
- int64_t t;
- is >> t;
- a = ModInt< mod >(t);
- return (is);
- }
- static ll get_mod() { return mod; }
- };
- using mint = ModInt< mod >;
- template <typename node, typename update>
- struct segTree{
- ll len;
- vector<node> t;
- vector<update> u;
- vector<bool> lazy;
- vector<ll> tl,tr;
- node identity_element;
- update identity_transformation;
- template<typename T>
- segTree(T &a){
- len = a.size();
- t.resize(4 * len);
- u.resize(4 * len);
- lazy.resize(4 * len);
- tl.resize(4 * len);
- tr.resize(4 * len);
- identity_element = node();
- identity_transformation = update();
- build(a,1,0,len-1);
- }
- template <typename T>
- void build(const T &a, const ll &v, const ll &l, const ll &r){
- tl[v]=l;
- tr[v]=r;
- if (l == r){
- t[v]=a[l];
- return;
- }
- ll tm = (l + r) >> 1;
- build(a, v << 1, l, tm);
- build(a, v << 1 | 1, tm + 1, r);
- t[v].merge(t[v << 1], t[v << 1 | 1]);
- }
- void apply(const ll &v, update val){
- if (tl[v] != tr[v]){
- lazy[v] = 1;
- u[v].combine(val, tl[v], tr[v]);
- }
- val.apply(t[v], tl[v], tr[v]);
- }
- void pushdown(const ll &v){
- if(lazy[v]){
- apply(v << 1, u[v]);
- apply(v << 1 | 1, u[v]);
- u[v] = identity_transformation;
- lazy[v] = 0;
- }
- }
- // rupd = range update
- void rupd(const ll &v,const ll &l, const ll &r, update val){
- if (l > tr[v] || r < tl[v])
- return;
- if (tl[v] >= l && tr[v] <= r){
- apply(v,val);
- return;
- }
- pushdown(v);
- rupd(v << 1, l, r, val);
- rupd(v << 1 | 1, l, r, val);
- t[v].merge(t[v << 1], t[v << 1 | 1]);
- }
- node query(const ll &v,const ll &l, const ll &r){
- if (l > tr[v] || r < tl[v])
- return identity_element;
- if (tl[v] >= l && tr[v] <= r)
- return t[v];
- pushdown(v);
- node a,b,ans;
- a=query(v*2,l,r);
- b=query(v*2+1,l,r);
- ans.merge(a,b);
- return ans;
- }
- node query(const ll &l, const ll &r){
- return query(1, l, r);
- }
- void rupd(const ll &l, const ll &r, update upd){
- rupd(1, l, r, upd);
- }
- };
- struct node1{
- mint prosum=0;
- mint asum=0;
- mint bsum=0;
- // use more variables if you want more information
- // these default values should be identity_element
- node1() {}
- node1(pair<ll,ll> p){
- prosum=(p.first*p.second);
- asum=p.first;
- bsum=p.second;
- }
- void merge(const node1 &l, const node1 &r){
- prosum=(l.prosum+r.prosum);
- asum=(l.asum+r.asum);
- bsum=(l.bsum+r.bsum);
- }
- };
- struct update1{
- mint v=0;
- mint type=-1;
- // use more variables if you want more information
- // these default values should be identity_transformation
- update1() {}
- update1(ll val,ll t){
- v=val;
- type=t;
- }
- // combine the current update1 with the other update1
- void combine(update1 &other, const ll &tl, const ll &tr){
- // only needed for range updates
- if(other.type==1){
- type=1;
- }else if(other.type==2){
- type=2;
- }
- v+=other.v;
- }
- // store the correct information in the node1 x
- void apply(node1 &x, const ll &tl, const ll &tr){
- if(type==1){
- x.asum=(x.asum+(v*(tr-tl+1)));
- x.prosum=(x.prosum+(v*x.bsum));
- }else if(type==2){
- x.bsum=(x.bsum+(v*(tr-tl+1)));
- x.prosum=(x.prosum+(v*x.asum));
- }
- }
- };
- void solve(){
- ll n,q;
- cin>>n>>q;
- vector<pair<ll, ll>> ab(n+5);
- for(ll i=1;i<=n;i++){
- cin>>ab[i].first;
- }
- for(ll i=1;i<=n;i++){
- cin>>ab[i].second;
- }
- segTree<node1,update1> st(ab);
- while(q--){
- ll t;
- cin>>t;
- if(t==1){
- ll l,r;
- cin>>l>>r;
- ll x;
- cin>>x;
- st.rupd(l,r,update1(x,1));
- }else if(t==2){
- ll l,r;
- cin>>l>>r;
- ll x;
- cin>>x;
- st.rupd(l,r,update1(x,2));
- }else{
- ll l,r;
- cin>>l>>r;
- cout<<st.query(l,r).prosum<<'\n';
- }
- }
- }
- signed main(){
- ios_base::sync_with_stdio(false), cin.tie(nullptr);
- //freopen("input.txt","r",stdin);
- //freopen("output.txt","w",stdout);
- int t=1;
- // cin>>t;
- for(int i=1;i<=t;i++){
- solve();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment