結果

問題 No.3494 一点挿入区間和取得
コンテスト
ユーザー edon8618
提出日時 2026-04-03 22:37:08
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 175 ms / 6,000 ms
コード長 10,158 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 4,814 ms
コンパイル使用メモリ 380,148 KB
実行使用メモリ 8,704 KB
最終ジャッジ日時 2026-04-03 22:37:20
合計ジャッジ時間 9,335 ms
ジャッジサーバーID
(参考情報)
judge3_1 / judge5_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 23
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;



// #include <boost/multiprecision/cpp_int.hpp>
// using namespace boost::multiprecision;

#define ll long long
#define ld long double
#define rep(i, n) for (ll i = 0; i < (ll)(n); ++i)
#define vi vector<int>
#define vl vector<ll>
#define vd vector<double>
#define vb vector<bool>
#define vs vector<string>
#define vc vector<char>
#define ull unsigned long long
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()

template<class T, class U>
inline bool chmax(T &a, const U &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T, class U>
inline bool chmin(T &a, const U &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}


// #define ll int
// #define ll int128_t
// #define ll int256_t
// #define ll cpp_int


constexpr ll inf = (1ll << 60);
// constexpr ll inf = (1 << 30);
// const double PI=3.1415926535897932384626433832795028841971;

// ll rui(ll a,ll b){
//     if(b==0)return 1;
//     if(b%2==1) return a*rui(a*a,b/2);
//     return rui(a*a,b/2);
// }

// vl fact;
// ll kai(ll n){
//     fact.resize(n,1);
//     rep(i,n-1)fact[i+1]=fact[i]*(i+1);
// }

// using mint = ld;
using mint = modint998244353;//static_modint<998244353>
// using mint = modint1000000007;//static_modint<1000000007>
// using mint = static_modint<922267487>;   // 多分落とされにくい NOT ntt-friendly
// using mint = static_modint<469762049>;   // ntt-friendly
// using mint = static_modint<167772161>;   // ntt-friendly
// using mint = modint;//mint::set_mod(mod);

// ll const mod=1000000007ll;
// ll const mod=998244353ll;
// ll modrui(ll a,ll b,ll mod){
//     a%=mod;
//     if(b==0)return 1;
//     if(b%2==1) return a*modrui(a*a%mod,b/2,mod)%mod;
//     return modrui(a*a%mod,b/2,mod)%mod;
// }

// ll inv(ll x){
//     x%=mod;
//     return modrui(x,mod-2);
// }

// void incr(vl &v,ll n){// n進法
//     ll k=v.size();
//     v[k-1]++;
//     ll now=k-1;
//     while (v[now]>=n)
//     {
//         v[now]=0;
//         if(now==0)break;
//         v[now-1]++;
//         now--;
//     }
//     return;
// }

// vector<mint> fact,invf;
// void init_modfact(ll sz){
//     fact.resize(sz);
//     invf.resize(sz);
//     fact[0]=1;
//     rep(i,sz-1){
//         fact[i+1]=fact[i]*(i+1);
//     }
//     invf[sz-1]=1/fact[sz-1];
//     for(ll i=sz-2; i>=0; i--){
//         invf[i]=invf[i+1]*(i+1);
//     }
// }
// mint choose(ll n,ll r){
//     if(n<r || r<0)return 0;
//     return fact[n]*invf[r]*invf[n-r];
// }

vector<mint> modpow,invpow;
void init_modpow(ll x,ll sz){
    mint inv=1/mint(x);
    modpow.assign(sz,1);
    invpow.assign(sz,1);
    rep(i,sz-1){
        modpow[i+1]=modpow[i]*x;
        invpow[i+1]=invpow[i]*inv;
    }
}
// long long phi(long long n) {// O(sqrt(n))
//     long long res = n;
//     for (long long i = 2; i * i <= n; i++) {
//         if (n % i == 0) {
//             res -= res / i;
//             while (n % i == 0) n /= i;
//         }
//     }
//     if (n > 1) res -= res / n;
//     return res;
// }


ll ceil(ll a,ll b){
    ll k=a/b;
    if(b*(k-1)>=a)return k-1;
    if(b*k>=a)return k;
    if(b*(k+1)>=a)return k+1;
    return 0;
}
ll floor(ll a,ll b){
    ll k=a/b;
    if(b*(k+1)<=a)return k+1;
    if(b*k<=a)return k;
    if(b*(k-1)<=a)return k-1;
    return 0;
}





// https://judge.yosupo.jp/submission/326817
template<
    typename S, typename F,
    S (*op)(S, S),
    S (*e)(),
    S (*mapping)(F, S),
    F (*composition)(F, F),
    F (*id)(),
    S (*rev_op)(S)
>
struct implicit_treap {
    struct Node {
        S val;   // single element value
        S sum;   // aggregated value of subtree (順序依存)
        int sz;
        unsigned pri;
        Node *l, *r;
        F lazy;
        bool has_lazy;
        bool rev; // reverse flag
        Node(const S &v, unsigned p): val(v), sum(v), sz(1), pri(p), l(nullptr), r(nullptr), lazy(id()), has_lazy(false), rev(false) {}
        void pull(){
            // subtree の集合を左->val->右 の順で計算
            sum = val;
            sz = 1;
            if(l){ sum = op(l->sum, sum); sz += l->sz; }
            if(r){ sum = op(sum, r->sum); sz += r->sz; }
        }
        void apply_lazy(const F &f){
            // 写像 f を val と sum に適用
            val = mapping(f, val);
            sum = mapping(f, sum);
            if(has_lazy){
                // 新しい f を既存 lazy の前に適用する(apply f after existing lazy)
                lazy = composition(f, lazy);
            }else{
                lazy = f;
                has_lazy = true;
            }
        }
        void apply_rev(){
            // 節点を反転:子をswapし、val/sum を rev_op で反転表現に変える
            rev = !rev;
            std::swap(l, r);
            val = rev_op(val);
            sum = rev_op(sum);
        }
        void push(){
            // 子へ遅延写像を伝搬
            if(has_lazy){
                if(l) l->apply_lazy(lazy);
                if(r) r->apply_lazy(lazy);
                lazy = id();
                has_lazy = false;
            }
            // 子へ反転フラグを伝搬(apply_rev は子の構造も入れ替える)
            if(rev){
                if(l) l->apply_rev();
                if(r) r->apply_rev();
                rev = false;
            }
        }
    };

    Node *root;
    std::mt19937_64 rng;

    implicit_treap(): root(nullptr), rng((unsigned)chrono::high_resolution_clock::now().time_since_epoch().count()) {}

    ~implicit_treap(){
        destroy(root);
    }

    void destroy(Node *t){
        if(!t) return;
        destroy(t->l);
        destroy(t->r);
        delete t;
    }

    int size() const { return root ? root->sz : 0; }

    Node* make_node(const S &v){
        return new Node(v, (unsigned)(rng() >> 1));
    }

    // split by first k elements: [0,k) and [k, n)
    pair<Node*, Node*> split(Node *t, int k){
        if(!t) return {nullptr, nullptr};
        t->push();
        int lsz = t->l ? t->l->sz : 0;
        if(k <= lsz){
            auto pr = split(t->l, k);
            t->l = pr.second;
            t->pull();
            return {pr.first, t};
        }else{
            auto pr = split(t->r, k - lsz - 1);
            t->r = pr.first;
            t->pull();
            return {t, pr.second};
        }
    }

    Node* merge(Node *a, Node *b){
        if(!a) return b;
        if(!b) return a;
        if(a->pri > b->pri){
            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;
        }
    }

    // build from vector of S
    Node* build_from_vector(const vector<S> &v){
        Node *t = nullptr;
        for(const S &x : v){
            t = merge(t, make_node(x));
        }
        return t;
    }

    void build(const vector<S> &v){
        destroy(root);
        root = build_from_vector(v);
    }

    // get element at index i (0-index)
    S get(int i){
        Node *t = root;
        while(t){
            t->push();
            int lsz = t->l ? t->l->sz : 0;
            if(i < lsz) t = t->l;
            else if(i == lsz) return t->val;
            else { i -= lsz + 1; t = t->r; }
        }
        return e(); // out of range -> return identity
    }

    // insert element at position pos (0-index, insert before pos)
    void insert(int pos, const S &v){
        assert(0<=pos && pos<=(this->size()));
        auto pr = split(root, pos);
        Node *n = make_node(v);
        root = merge(merge(pr.first, n), pr.second);
    }

    // erase element at position pos
    void erase(int pos){
        assert(0<=pos && pos<=(this->size()));
        auto a = split(root, pos);
        auto b = split(a.second, 1); // b.first is node to erase
        destroy(b.first);
        root = merge(a.first, b.second);
    }

    // apply mapping f to range [l, r) (0-index half-open)
    void apply(int l, int r, const F &f){
        assert(0<=l && r<=(this->size()) && l<=r);
        if(l >= r) return;
        auto a = split(root, l);
        auto b = split(a.second, r - l);
        if(b.first) b.first->apply_lazy(f);
        root = merge(a.first, merge(b.first, b.second));
    }

    // reverse range [l,r) (0-index half-open)
    void range_reverse(int l, int r){
        assert(0<=l && r<=(this->size()) && l<=r);
        if(l >= r) return;
        auto a = split(root, l);
        auto b = split(a.second, r - l);
        if(b.first) b.first->apply_rev();
        root = merge(a.first, merge(b.first, b.second));
    }

    // query aggregate on [l, r)
    S prod(int l, int r){
        assert(0<=l && r<=(this->size()) && l<=r);
        if(l >= r) return e();
        auto a = split(root, l);
        auto b = split(a.second, r - l);
        S res = b.first ? b.first->sum : e();
        root = merge(a.first, merge(b.first, b.second));
        return res;
    }

    // inorder -> vector
    void to_vector(Node *t, vector<S> &out){
        if(!t) return;
        t->push();
        to_vector(t->l, out);
        out.push_back(t->val);
        to_vector(t->r, out);
    }
    vector<S> to_vector(){
        vector<S> v;
        v.reserve(size());
        to_vector(root, v);
        return v;
    }
};

// struct S{};
#define S ll
// struct F{};
#define F ll
S op(S l,S r){return l+r;}

S e(){return 0;}

S mapping(F f,S s){return s;}

F id(){return 0;}

F composition(F f,F g){return 0;}

S rev_op(S s){return s;}

void solve(){
    ll n,q;
    cin >> n >> q;

    implicit_treap<S,F,op,e,mapping,composition,id,rev_op> treap;
    rep(i,n){
        ll a;
        cin >> a;
        treap.insert(i,a);
    }
    while(q--){
        ll i,x,l,r;
        cin >> i >> x >> l >> r;
        l--;

        treap.insert(i,x);
        cout << treap.prod(l,r) << endl;
    }
}

int main(){
    // ios::sync_with_stdio(false);
    // std::cin.tie(nullptr);


    ll t = 1;
    // cin >> t;
    while (t--) solve();
}
0