AcWing 242. 一个简单的整数问题(树状数组解法)

AcWing 242. 一个简单的整数问题

题意

给定长度为N的数列A,然后输入M行操作指令。
第一类指令形如“C l r d”,表示把数列中第l~r个数都加d。
第二类指令形如“Q X”,表示询问数列中第x个数的值。
对于每个询问,输出一个整数表示答案。

分析

如果这题不是使用线段树,而是使用树状数组来解决,怎么做呢?怎么思考呢?

树状数组仅支持单点修改和区间查询,但这题是要求区间修改和单点查询,好像跟树状数组反着来的。。。

仔细观察一下,其实把A[l]到A[r]都加d,就是把l到r这个区间中的数都加d, r+1到n这个区间中的数都减d,因此可以使用一个额外数组B来维护区间的变化, 至于查询第x个数,就是A[x]+ B[1]~B[x]

注意

这题序列元素的范围是10亿,因此有些变量需要使用long long

代码

#include <iostream>
#include <cstring>
#define ll long long

using namespace std;

const int N = 1e5 + 5;

//a为存储数据的数组,b为树状数组
ll a[N];
int b[N];
//n为序列长度,m为操作指令次数
int n, m;

//lowbit操作
int lowbit(int x) {
    return x & -x;
}

//区间查询
ll sum(int x) {
    ll ans = 0;
    while (x) {
        ans += b[x];
        x -= lowbit(x);
    }
    return ans;
}

//单点修改
void add(int x, int v) {
    while (x <= n) {
        b[x] += v;
        x += lowbit(x);
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);//输入序列
    while (m--) {
        char op[2];
        scanf("%s", op);
        if (op[0] == 'C') {
            int l, r, d;
            scanf("%d%d%d", &l, &r, &d);
            //b[l]加d,相当于a[l]~a[n]都加d
            add(l, d);   
            //b[r + 1]减d,相当于a[r + 1]~a[n]都减d
            add(r + 1, -d);
        } else {
            int x;
            scanf("%d", &x);
            printf("%lld\n", a[x] + sum(x));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值