在对一个数列求区间和时,我们通常采用前缀和来完成,但如果修改其中某值,就需要将所有后面前缀和修改,这是非常麻烦的,那么就可以用树状数组。
树状数组原理大致就是将基础元素合并成越来越大的集合,修改则只需修改集合值即可,避免的具体对每个前缀操作。
首先我们来了解一下这个函数
int lowbit(int t){
return t& -t;
}
这个函数就是求t最低位为1和其后零的十进制
如10010 就是 二进制的10 十进制的2
那么为什么要用这个呢?
如果让 x+=lowbit(x);
比如1 2 4 8 16 32...
这是不是可以将该数组划分成不同部分
对int 最多就32 个层
可以看这样一个图
数组中偶数位保存是一个个的和,奇数的lowbit是1,减去就变成前面偶数所包含的集合
代码实现:
先输入初始数组
for(int i=1;i<=n;i++) scanf("%d",&dp[i]);
再初始化树状数组
void add(int t,int u){
for(int i=t;i<=n;i+=lowbit(i)) v[i]+=u;
}
void init(){
for(int i=1;i<=n;i++) add(i,dp[i]);
}
如果求和left到right,传入查找left应减一,因为是是[left,right]闭区间
int sums(int t){
int res=0;
for(int i=t;i>0;i-=lowbit(i)) res+=v[i];
return res;
}
主代码
cout<<sums(y)-sums(x-1)<<endl;
若元素改变,则改变包含他的集合
t为下标,u为增加的值
for(int i=t;i<=n;i+=lowbit(i)) v[i]+=u;
谢谢观看!!!