向上更新,建树,求区间和,修改节点值
向上更新:
返回左右节点值的和
建树:
如果是叶子节点,赋值结构体的左区间,右区间,值
如果不是叶子节点,那么先求中点,建左子树(l到mid),建右子树(mid+1到r)
最后向上更新pushup
查询区间和:
如果这个区间被覆盖,直接返回值
如果没有被覆盖,求中间节点
定义一个sum
1️⃣如果所求区间左节点小于或等于mid,去查询这个左区间的值 ,并加到sum中
2️⃣如果所求区间右节点大于mid,去查询这个右区间的值,并加到sum中
修改节点值:
如果找到节点 直接加上目标值
如果没找到,求中点
如果目标节点 <=mid 向左寻找
如果目标节点 >mid 向右寻找
修改后要向上更新
树状数组
构建树状数组:用change函数构建
for (int i = 1;i <= n;i++) {scanf("%d",&arr[i]);}for (int i = 1;i <= n;i++) {change(i,arr[i]);}
暴力:
#include <iostream>
#include <cstdio>using namespace std;const int N = 100010;int f[N];int main() {int n , m;scanf("%d%d",&n,&m);for (int i = 1;i <= n;i++) {scanf("%d",&f[i]);}while (m--) {int k,a,b;scanf("%d%d%d",&k,&a,&b);if (k == 1) {f[a] += b;}else {int num = 0;for (int i = a;i <= b;i++) {num += f[i];}printf("%d\n",num);}}return 0;
}
线段树:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>using namespace std;const int N = 100010;struct Node{int l,r;int sum;
}tr[4*N];int w[N];
int n,m;
int k,a,b;void pushup(int u) { tr[u].sum = tr[u<<1].sum + tr[u<<1|1].sum;
}void build(int u,int l,int r) {if (l == r) tr[u] = {l,r,w[r]};else {tr[u] = {l,r};int mid = l + r >> 1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(u);}
}int query(int u,int x,int y) {if (x <= tr[u].l && y >= tr[u].r) return tr[u].sum;int mid = tr[u].l + tr[u].r >> 1;int sum = 0;if (x <= mid) sum = query(u<<1,x,y);if (y > mid) sum += query(u<<1|1,x,y);return sum;
}void modify(int u,int x,int v) {if (tr[u].l == tr[u].r) tr[u].sum += v;else {int mid = tr[u].l + tr[u].r >> 1;if (x <= mid) modify(u<<1,x,v);if (x > mid) modify(u<<1|1,x,v);pushup(u);}
}int main() {scanf("%d%d",&n,&m);for (int i = 1;i <= n;i++) {scanf("%d",&w[i]);}build(1,1,n);while (m--) {scanf("%d%d%d",&k,&a,&b);if (k == 0) printf("%d\n",query(1,a,b));else modify(1,a,b); }return 0;
}
树状数组:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>using namespace std;const int N = 100010;int n , m;
int k , a ,b;
int tr[N],arr[N];int lowbit(int x) {return x & -x;
}void add(int x,int v) {while (x <= n) tr[x]+=v,x += lowbit(x);
}int query(int x)
{int res = 0;while (x) res += tr[x],x -= lowbit(x);return res;
}int main() {scanf("%d%d",&n,&m);for (int i = 1;i <= n;i++) {scanf("%d",&arr[i]);}for (int i = 1;i <= n;i++) {add(i,arr[i]);}while (m --) {scanf("%d%d%d",&k,&a,&b);if (k == 0) {printf("%d\n",query(b) - query(a-1));}else {add(a,b);}}return 0;
}