1 条题解

  • 0
    @ 2026-10-26 13:00:02

    思路与算法

    令差分d[i]=a[i]-a[i-1],区间加x等价于d[l]+=x、d[r+1]-=x。前r项的和为Σ(i≤r)(r-i+1)d[i]=r*Σd[i]-Σ(i-1)d[i]。用两棵树状数组分别维护d[i]与(i-1)d[i],据此前缀公式求区间和。初始化时把各a[i]作为单点区间加,操作沿用相同函数。

    正确性说明

    差分的前缀还原出每项值,区间两端的差分改动恰好让区间内元素统一增加x、区间外不变。交换有限求和次序得到前缀和恒等式,两棵BIT的前缀查询分别给出该式两部分,所以前缀值准确。区间[l,r]再用prefix(r)-prefix(l-1),因而所有更新和查询都符合协议,负数增量也满足同一线性关系。

    复杂度

    初始化两棵数组O(n),逐个单点加入O(n log n),q次操作O(q log n),总时间O((n+q)log n),空间O(n),两份long long数组约16MB。包括加权差分在内用64位;n,q≤10^6、|a|,|x|≤10^6,整个区间和绝对值不超过10^18+10^12,仍在signed64内。

    易错点

    不是单点修改或区间赋值,操作1表示区间每项加x。r=n时r+1超出BIT有效长度,更新循环直接结束即可。必须算l-1前缀、并把乘法先提升为long long。库内J0344只有10万且限定正数,本题百万规模并允许负数,作为完整范围版本保留。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    struct BIT {
        int n;
        vector<long long> a;
        BIT(int n) : n(n), a(n + 1) {
        }
        void add(int x, long long v) {
            for (; x <= n; x += x & -x)
                a[x] += v;
        }
        long long sum(int x) {
            long long s = 0;
            for (; x; x -= x & -x)
                s += a[x];
            return s;
        }
    };
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, q;
        cin >> n >> q;
        BIT a(n), b(n);
        auto add = [&](int l, int r, long long x) {
            a.add(l, x);
            a.add(r + 1, -x);
            b.add(l, x * (l - 1));
            b.add(r + 1, -x * r);
        };
        auto prefix = [&](int r) {
            return r * a.sum(r) - b.sum(r);
        };
        for (int i = 1; i <= n; ++i) {
            long long x;
            cin >> x;
            add(i, i, x);
        }
        while (q--) {
            int op, l, r;
            cin >> op >> l >> r;
            if (op == 1) {
                long long x;
                cin >> x;
                add(l, r, x);
            } else
                cout << prefix(r) - prefix(l - 1) << '\n';
        }
    }
    
    • 1

    【例 2】A Simple Problem with Integers(百万规模,允许负数)

    信息

    ID
    1741
    时间
    5000ms
    内存
    512MiB
    难度
    普及
    标签
    递交数
    1
    已通过
    1
    上传者