树状数组 1 :单点修改,区间查询
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
struct BIT {
ll sum[N];
inline int lowbit(int x) {
return x & (-x);
}
void add(int x, int val) {
while (x < N)
sum[x] += val, x += lowbit(x); //走向父节点
}
inline ll query(int x) { //查询
ll res = 0;
while (x)
res += sum[x], x -= lowbit(x); //走向子节点
return res;
}
} T;
void Main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int val;
cin >> val;
T.add(i, val); //在i的位置加上val,原先数组为0,算是一个赋值过程
}
for (int i = 1; i <= m; i++) {
int op, a, b;
cin >> op >> a >> b;
if (op == 1)
T.add(a, b);
if (op == 2)
cout << T.query(b) - T.query(a - 1) << endl; //求区间和
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
Main();
return 0;
}
树状数组 2
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int const maxn = 1e6 + 10;
struct BIT {
ll tree[maxn];
inline int lowbit(int x) {
return x & (-x);
}
inline void add(int i, int x, int n) {//在连续的区间分别加上x
while (i <= n) {//对于树状数组就只要在几个节点上加上x,就能达到那样的效果,优势就在这
tree[i] += x;
i += lowbit(i);
}
}
inline ll query(int i) { //查询
ll ans = 0;
while (i >= 1) {
ans += tree[i], i -= lowbit(i); //走向子节点
}
return ans;
}
} T;
void Main() {
int n, q;
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++) {
int val;
scanf("%d", &val);
T.add(i, val, n);//这里构建树状数组的方法和上一题大同小异,都是一样的原理,这题的add写成这样,主要是为了迎合后面在一段连续区间+x的需求
T.add(i + 1, -val, n);
}
for (int j = 1; j <= q; j++) {
int op;
scanf("%d", &op);
if (op == 1) {
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
T.add(l, x, n);
T.add(r + 1, -x, n);
} else if (op == 2) {
int i;
scanf("%d", &i);
printf("%lld\n", T.query(i));
}
}
}
int main() {
Main();
return 0;
}