树状数组:是一个数据结构
- 基本用途:维护序列的前缀和
作用:
- 快速求前缀和(时间复杂度:O(logn))
- 修改某一个数(时间复杂度:O(logn))
lowbit函数
int lowbit(int x){
return x & -x;
}
建树
//原树状数组
scanf("%lld %lld",&n,&m);
for(int i = 1; i <= n; i ++ ){
scanf("%lld",&x);
add(i,x);
}
//差分树状数组
scanf("%lld %lld",&n,&m);
ll now = 0;
for(int i = 1; i <= n; i ++ ){
ll x;
scanf("%lld",&x);
add(i,x - now);
now = x;
}
主要操作:
- 单点修改:
- 给序列中的一个数tr[x]加上y,同时正确维护序列的前缀和
void add(int x,int c){
for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
- 区间查询:
int sum(int x){
int res = 0;
for(int i = x; i; i-=lowbit(i)) res+=tr[i];
return res;
}
- 区间修改:
建树有所不同,建立差分树状数组
add(l,x);add(r + 1,-x);
- 单点查询
sum(x);
- 更新过程是每次加了个二进制的低位1(101+1 ->110, 110 + 10 -> 1000, 1000 + 1000 -> 10000)
- 查询过程每次就是去掉了二进制中的低位1(1111 - 1 -> 1110, 1110 - 10 -> 1100, 1100 - 100 -> 1000)