1. 程式人生 > 其它 >AcWing 242. 一個簡單的整數問題

AcWing 242. 一個簡單的整數問題

題目傳送門

演算法分析
樹狀陣列(變型型別:差分)

樹狀陣列主要解決的是

1、a[x] += c (單點修改)
2、求a[L ~ R] (字首和)
本題要求求的是

1、a[L ~ R] += c
2、求a[x]
因為 字首和差分 是一種逆運算,因此本題將原陣列a[]轉換 差分陣列b[],就變成了樹狀陣列的模型

1、a[L ~ R] += c 等價於 b[L] += c,b[R + 1] -= c
2、求a[x] 等價於b[1 ~ x]的字首和

注意:在求字首和時,要特別注意資料範圍,防止爆\(int\)

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 100010;

int n, m;
int a[N];

//注意下這裡與標準模板的不同,因為求和可能會超過int上限,需要開long long
// t[i]表示樹狀陣列i結點覆蓋的範圍和
LL t[N];

//返回非負整數x在二進位制表示下最低位1及其後面的0構成的數值
int lowbit(int x) {
    return x & -x;
}
//將序列中第x個數加上k
void add(int x, int k) {
    for (int i = x; i <= n; i += lowbit(i)) t[i] += k;
}
//查詢序列前x個數的和
LL sum(int x) {
    int sum = 0;
    for (int i = x; i; i -= lowbit(i)) sum += t[i];
    return sum;
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];
    //樹狀陣列初始化,儲存差分值
    for (int i = 1; i <= n; i++) add(i, a[i] - a[i - 1]);
    while (m--) {
        char op;
        int l, r, d;
        cin >> op >> l;
        if (op == 'C') { //修改
            cin >> r >> d;
            //差分,在l處加上d,在r+1位置減去d
            add(l, d), add(r + 1, -d);
        } else
            printf("%lld\n", sum(l)); //求字首和
    }
    return 0;
}