本题好像只要用支持区间加,区间重置的线段树也能过,但是不能够在过程中取模?

大思路就是,我们给原数组排序,因为每次加减都是在所有数的上面操作,然后加法不会改变顺序,而减法可能会导致从某个位置开始往左全是0,具有二段性,我们可以二分找到这个位置,然后将左边的全部置为0,右边的正常减就行了。

由于涉及到了比大小,所以不能在中间取模,所以最后的求和数会很大,直接用了__int128

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

typedef __int128 ll;

const int MOD = 1e9 + 7;

class LazySegmentTree {
public:
    LazySegmentTree(int _n) {
        n = _n;
        sum.assign(4 * n, 0);
        add_lazy.assign(4 * n, 0);
        reset_lazy.assign(4 * n, -1);
    }

    void add_update(int start, int end, int v) {
        _add_update(0, 0, n - 1, start, end, v);
    }

    void reset_update(int start, int end, int v) {
        _reset_update(0, 0, n - 1, start, end, v);
    }

    ll query(int start, int end) {
        return _query(0, 0, n - 1, start, end);
    }

private:
    int n;
    vector<ll> sum;
    vector<ll> add_lazy;
    vector<ll> reset_lazy;

    void doSum(int o, int l, int r, int v) {
        sum[o] += (ll)(r - l + 1) * v;
        add_lazy[o] += v;
    }

    void doReset(int o, int l, int r, int v) {
        sum[o] = (ll)(r - l + 1) * v;
        reset_lazy[o] = v;
        add_lazy[o] = 0;
    }

    void push_down(int o, int l, int r) {
        if (reset_lazy[o] != -1) {
            int left = 2 * o + 1;
            int right = 2 * o + 2;
            int m = (l + r) / 2;
            doReset(left, l, m, reset_lazy[o]);
            doReset(right, m + 1, r, reset_lazy[o]);
            reset_lazy[o] = -1;
        }
        if (add_lazy[o] != 0) {
            int left = 2 * o + 1;
            int right = 2 * o + 2;
            int m = (l + r) / 2;
            int v = add_lazy[o];
            doSum(left, l, m, v);
            doSum(right, m + 1, r, v);
            add_lazy[o] = 0;
        }
    }

    void maintain(int o) {
        int left = 2 * o + 1;
        int right = 2 * o + 2;
        sum[o] = sum[left] + sum[right];
    }

    void _add_update(int o, int l, int r, int start, int end, int v) {
        if (start <= l && r <= end) {
            doSum(o, l, r, v);
            return;
        }
        push_down(o, l, r);
        int m = (l + r) / 2;
        int left = 2 * o + 1;
        int right = 2 * o + 2;
        if (m >= start) _add_update(left, l, m, start, end, v);
        if (m < end) _add_update(right, m + 1, r, start, end, v);
        maintain(o);
    }

    void _reset_update(int o, int l, int r, int start, int end, int v) {
        if (start <= l && r <= end) {
            doReset(o, l, r, v);
            return;
        }
        push_down(o, l, r);
        int m = (l + r) / 2;
        int left = 2 * o + 1;
        int right = 2 * o + 2;
        if (m >= start) _reset_update(left, l, m, start, end, v);
        if (m < end) _reset_update(right, m + 1, r, start, end, v);
        maintain(o);
    }

    ll _query(int o, int l, int r, int start, int end) {
        if (start <= l && r <= end) {
            return sum[o];
        }
        push_down(o, l, r);
        ll res = 0;
        int m = (l + r) / 2;
        int left = 2 * o + 1;
        int right = 2 * o + 2;
        if (m >= start) res += _query(left, l, m, start, end);
        if (m < end) res += _query(right, m + 1, r, start, end);
        return res;
    }
};
ll read() {
    string s;
    cin >> s;
    ll x = 0;
    int start = 0;
    bool neg = false;
    if (s[0] == '-') {
        neg = true;
        start = 1;
    }
    for (int i = start; i < s.size(); i++) {
        x = x * 10 + (s[i] - '0');
    }
    return neg ? -x : x;
}
void print(ll x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
int main() {
    ll n, k;
    n = read();k = read();
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    sort(a.begin(), a.end());
    LazySegmentTree tr(n);
    for (int i = 0; i < n; ++i) {
        tr.add_update(i, i, a[i]);
    }
    for (int _ = 0; _ < k; ++_) {
        int op, x;
        cin >> op >> x;
        if (op == 1) {
            tr.add_update(0, n - 1, x);
        } else {
            int l = 0, r = n;
            while (l < r) {
                int m = (l + r) / 2;
                ll val = tr.query(m, m);
                if (val >= x) {
                    r = m;
                } else {
                    l = m + 1;
                }
            }
            if (l < n) {
                tr.add_update(l, n - 1, -x);
            }
            if (l - 1 >= 0) {
                tr.reset_update(0, l - 1, 0);
            }
        }
    }
    ll res = tr.query(0, n - 1);
    print(res % MOD);
    return 0;
}