結果

問題 No.789 範囲の合計
ユーザー nu50218nu50218
提出日時 2024-08-24 05:42:31
言語 C++23(gcc13)
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 169 ms / 1,000 ms
コード長 3,849 bytes
コンパイル時間 4,361 ms
コンパイル使用メモリ 290,532 KB
実行使用メモリ 50,304 KB
最終ジャッジ日時 2024-08-24 05:42:39
合計ジャッジ時間 6,884 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,812 KB
testcase_02 AC 153 ms
41,216 KB
testcase_03 AC 47 ms
6,940 KB
testcase_04 AC 169 ms
46,208 KB
testcase_05 AC 133 ms
39,680 KB
testcase_06 AC 129 ms
41,472 KB
testcase_07 AC 43 ms
6,944 KB
testcase_08 AC 149 ms
50,304 KB
testcase_09 AC 136 ms
46,208 KB
testcase_10 AC 123 ms
28,544 KB
testcase_11 AC 102 ms
40,832 KB
testcase_12 AC 107 ms
40,832 KB
testcase_13 AC 2 ms
6,940 KB
testcase_14 AC 2 ms
6,944 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define debug(...) ((void)0)

#include <bits/stdc++.h>

template <class S, auto op, auto e, class Size = uint32_t>
struct sparse_segtree {
    static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>, "op must work as S(S, S)");
    static_assert(std::is_convertible_v<decltype(e), std::function<S()>>, "e must work as S()");
    static_assert(std::is_unsigned_v<Size>, "Size must be a signed integral type");

    sparse_segtree() : root(new node(nullptr)) {}

    void set(const Size p, const S x) {
        assert(p < max_size);
        root->set(p, x);
    }

    S get(const Size p) const {
        assert(p < max_size);
        return root->get(p);
    }

    S prod(const Size l, const Size r) const {
        assert(l <= r);
        assert(r < max_size);

        if (l == r) {
            return e();
        }

        return root->prod(l, r);
    }

   private:
    static constexpr Size max_size = (Size(1) << Size(std::numeric_limits<Size>::digits - 1));

    struct node {
        node *parent, *left, *right;
        S val;

        explicit node(node* p) : parent(p), val(e()){};

        void set(const Size p, const S x, const Size cur_l = 0, const Size cur_r = max_size) {
            if (cur_l + 1 == cur_r) {
                val = x;
                update();
                return;
            }

            const Size cur_mid = std::midpoint(cur_l, cur_r);

            // left
            if (p < cur_mid) {
                if (!left) left = new node(this);
                left->set(p, x, cur_l, cur_mid);
                return;
            }

            // right
            if (!right) right = new node(this);
            right->set(p, x, cur_mid, cur_r);
        }

        S get(const Size p, const Size cur_l = 0, const Size cur_r = max_size) const {
            if (cur_l + 1 == cur_r) return val;

            const Size cur_mid = std::midpoint(cur_l, cur_r);

            // left
            if (p < cur_mid) {
                return left ? left->get(p, cur_l, cur_mid) : e();
            }

            // right
            return right ? right->get(p, cur_mid, cur_r) : e();
        }

        S prod(const Size l, const Size r, const Size cur_l = 0, const Size cur_r = max_size) const {
            if (l <= cur_l && cur_r <= r) return val;

            const Size cur_mid = std::midpoint(cur_l, cur_r);

            if (r <= cur_mid) {
                return left ? left->prod(l, r, cur_l, cur_mid) : e();
            }
            if (cur_mid <= l) {
                return right ? right->prod(l, r, cur_mid, cur_r) : e();
            }

            return op(left ? left->prod(l, r, cur_l, cur_mid) : e(),
                      right ? right->prod(l, r, cur_mid, cur_r) : e());
        }

        void update() {
            // if not a leaf, update val
            if (left || right) {
                val = e();
                if (left) val = op(val, left->val);
                if (right) val = op(val, right->val);
            }
            if (parent) parent->update();
        }
    };

    node* root;
};

using namespace std;
using ll = long long;
using ld = long double;

using S = ll;
S op(S a, S b) { return a + b; }
S e() { return 0; }
using segtree = sparse_segtree<S, op, e>;

void solve(int) {
    int q;
    cin >> q;

    segtree st;
    ll ans = 0;

    for (int i = 0; i < q; i++) {
        int t;
        cin >> t;

        if (t == 0) {
            ll x, y;
            cin >> x >> y;
            st.set(x, st.get(x) + y);
            continue;
        }

        if (t == 1) {
            ll l, r;
            cin >> l >> r;
            ans += st.prod(l, r + 1);
            continue;
        }
    }

    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve(0);
}
0