【模板】树状数组

luogu-P3374 【模板】树状数组 1

luogu-P3368 【模板】树状数组 2

在这里稍微总结一下(luogu)上树状数组的两个模板。

稍微提一嘴(update())(query())的遍历次序。

(update())中$ x+=lowbit() $相当于每次加上从右往左数的(第一个(1)到最右边)的值,比如(1(1))(2(10))(4(100))(8(1000))

(query())中$ x-=lowbit() $相当于每次减去从右往左数的(第一个(1)到最右边)的值,比如(5(101))(4(100))0(000)

单点修改,区间求和
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;

int n, m, tr[N];

int lowbit(int x) {
    return x & (-x);
}

void update(int x, int k) {
    for (; x <= n; x += lowbit(x)) 
        tr[x] += k;
}

int query(int x) {
    int res = 0;
    for (; x; x -= lowbit(x)) 
        res += tr[x];
    return res;
}

void build() {
    for (int i = 1; i <= n; i++) {
        int a; cin >> a; update(i, a);
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    build();
    while (m--) {
        int d, a, b; cin >> d >> a >> b;
        if (d == 1) update(a, b);
        else cout << (query(b) - query(a - 1)) << endl;
    }
    return 0;
}
单点求值,区间修改
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;

int n, m;
int tr[N];

int lowbit(int x) {
    return x & (-x);
}

void updata(int x, int k) {
    for (; x <= n; x += lowbit(x)) tr[x] += k;
}

void build() {
    int now = 0, last = 0;
    for (int i = 1; i <= n; i++) {
        cin >> now; updata(i, now - last); last = now; //构造差分数组tr,使用树状数组维护
    }
}

int query(int x) {
    int ans = 0;
    for (; x; x -= lowbit(x)) ans += tr[x];
    return ans;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    build();
    while (m--) {
        int d; cin >> d;
        if (d == 1) {
            int x, y, k; cin >> x >> y >> k;
            updata(x, k); updata(y + 1, -k); //对区间[x,y]进行修改,只用修改tr[x]与tr[y+1]:
        } else {
            int x; cin >> x;
            cout << query(x) << endl; //查询第x个数则将tr[1]~tr[x]累加
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Nepenthe8/p/13697259.html