【模板】树状数组
在这里稍微总结一下\(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;
}