一般用于单点修改,区间查询
模板:
const int N = 1e6 + 10;
int tree[N];
int lowbit(int x) {
return x & -x;
}
void add(int x, int k) { // 修改
while(x <= n) {
tree[x] += k;
x += lowbit(x);
}
}
int find(int x) { // 查询
int res = 0;
while(x != 0) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
对于单点修改,区间查询的完整代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int tree[N];
int n, m;
int lowbit(int x) {
return x & -x;
}
void add(int x, int k) {
while(x <= n) {
tree[x] += k;
x += lowbit(x);
}
}
int find(int x) {
int res = 0;
while(x != 0) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i ++) {
int t;
cin >> t;
add(i, t);
}
for(int i = 1; i <= m; i ++) {
int op;
cin >> op;
if(op == 1) {
int x, k;
cin >> x >> k;
add(x, k);
}
else {
int x, y;
cin >> x >> y;
cout << find(y) - find(x - 1) << endl;
}
}
return 0;
}
而对于区间修改,单点查询的题,只需要运用前缀和与差分的知识做一点小修改即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int tree[N], a[N];
int n, m;
int lowbit(int x) {
return x & -x;
}
void add(int x, int k) {
while(x <= n) {
tree[x] += k;
x += lowbit(x);
}
}
int find(int x) {
int res = 0;
while(x != 0) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
}
for(int i = 1; i <= m; i ++) {
int op;
cin >> op;
if(op == 1) {
int x, y, k;
cin >> x >> y >> k;
add(x, k); // 根据差分只需要让 tree[x] + k 即可保证区间的值都加上了k
add(y + 1, - k); // 到区间右端时,只需让 tree[x + 1] - k 即可保证区间以后的值不改变
}
else {
int x;
cin >> x;
cout << find(x) + a[x] << endl; // 查询的值即为数组的前缀和
}
}
return 0;
}
标签:树状,int,tree,cin,add,数组,区间,op
From: https://www.cnblogs.com/yishujia/p/18189767