树状数组:
用二进制思想解决大范围区间和问题。 注意:树状数组用于 单点更新。
基础模版含三个函数:
- lowbit(x),表示 x 二进制的最低位,如 6的二进制是110,lowbit(6) = 2
- 单点更新update函数,单点更新的并不是原数组,而是后缀数组C .// 数组值C[i] 表示从 i 开始向左数lowbit(i)个数的 和
- 查询函数,查询 区间[1,i]的和
const int maxn = 5e4 + 10;
int c[maxn];
int n;
#define lowbit(x) ((x) & (-x))
void update(int i,int val){ //更新后缀和
while(i <= n){
c[i] += val;
i += lowbit(i);
}
}
int query(int i){ //查询前缀和
int ret = 0;
while(i){
ret += c[i];
i -= lowbit(i);
}
return ret;
}
二维树状数组:
二维树状数组可以解决的问题,对于一个矩阵,有Q次操作,更改或查询,对某个位置的值加上一个值X,或查询一个子矩阵的和。
和一维树状数组差不多,update与query函数都套两重while
代码:
#define lowbit(x) ((x) & (-x));
///n * n
void update(int x, int y, int z){ //将点(x, y)加上z
int memo_y = y;
while(x <= n){
y = memo_y;
while(y <= n)
tree[x][y] += z, y += lowbit(y);
x += lowbit(x);
}
}
int query(int x, int y){//求左上角为(1,1)右下角为(x,y) 的矩阵和
int res = 0, memo_y = y;
while(x){
y = memo_y;
while(y)
res += tree[x][y], y -= lowbit(y);
x -= lowbit(x);
}
return res;
}