AcWing 243. 一个简单的整数问题2(树状数组的区间增加和区间查询)

在上一道题中,我们用树状数组维护了原序列的差分数组,得到了不同操作对原序列的累计影响:

\sum_{i=1}^{x}b[i]

在这道题中,我们需要求出这些累计影响的前缀和,即:

\sum_{i=1}^{x}\sum_{j=1}^{i}b[j]

我们对这个式子变形一下:

\sum_{i=1}^{x}\sum_{j=1}^{i}= \sum_{i=1}^{x}((x-i+1)*b[i])=(x+1)\sum_{i=1}^{x}b[i]-\sum_{i=1}^{x}(i*b[i])

为什么能这么变形呢?

我们画图解释:

 这样,我们只要维护两个树状数组(i*b[i])和(b[i])的即可.

具体见代码实现:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n, m;
int a[N], sum[N];
int c0[N], c1[N];//c0维护的是b[i], c1维护的是i * b[i]
int ask(int c[], int x){
    int ans = 0;
    for (; x; x -= x & -x)
        ans += c[x];
    return ans;
}

void add(int c[], int x, int y){
    for (; x <= n; x += x & -x)
        c[x] += y;
}
signed main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i){
        cin >> a[i];
        sum[i] = sum[i - 1] + a[i];
    }
    while (m--){
        string op;
        cin >> op;
        if (op == "C"){
            int l, r, d;
            cin >> l >> r >> d;
            add(c0, l, d);
            add(c0, r + 1, -d);
            add(c1, l, l * d);
            add(c1, r + 1, -((r + 1) * d));
        } else{
            int l, r;
            cin >> l >> r;
            cout << ((r + 1) * ask(c0, r) - ask(c1, r)) - (l * ask(c0, l - 1) - ask(c1, l - 1)) + sum[r] - sum[l - 1] << '\n';
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值