算法基础之树状数组

文章目录

树状数组

树状数组能解决的最关键的问题就是能够 O ( log ⁡ n ) O(\log n) O(logn)内,给某个位置上的数,加上一个数,或者求前缀和

他和前缀和数组的区别就是,树状数组支持修改原数组的内容,而前缀和数组不支持,需要重新求前缀和数组

总结一下树状数组能做的操作就是单点修改和区间查询,对于他的其他的功能,例如区间修改,单点查询,区间修改,区间查询都是使用差分的思想转化成最基础的思想

这里我们需要利用图像来表示

屏幕截图 2024-01-25 110626.png

这里的树状数组虽然画出来是个树,但本质上还是一维数组

其中的任意一个数字其实表示的是一段数的和,例如 C [ 8 ] = A [ 1 ] + ⋯ + A [ 8 ] C[8]=A[1]+\dots+A[8] C[8]=A[1]++A[8]

那么对于 C [ x ] C[x] C[x],我们如何确定x的层数呢,其实是可以利用x的二进制表示,其中末尾有几个0,就是第几层的数字,假设他最后有k个0,那么 C [ x ] = ∑ x − 2 k + 1 x A [ x ] C[x]=\sum_{x-2^k+1}^xA[x] C[x]=x2k+1xA[x],C++中有一个lowbit(x)函数,可以返回 2 k 2^k 2k,因此这个表达式也可以写成 C [ x ] = ∑ x − l o w b i t ( x ) + 1 x A [ x ] C[x]=\sum_{x-lowbit(x)+1}^xA[x] C[x]=xlowbit(x)+1xA[x],补充这里这里的lowbit(x)函数的原理就是位运算 x & − x x\&-x x&x

有了这部分的原理之后,我们就可以有两个操作

首先就是求前缀和,例如我们想求前x项的和,结果就是 C [ x ] + C [ x − l o w b i t ( x ) ] + … C[x]+C[x-lowbit(x)]+\dots C[x]+C[xlowbit(x)]+

写成代码就可以是

int res = 0;
for(i=x;i>0;i-=lowbit(x))
{
    res += c[i];
}
return res;

那比较难理解的就是更新的过程,假设我们要给A[x]+v,严格证明过于复杂,我们这里只给出出结论和代码

由于我们更改了原数组中的一个数值,那么他对应的所有父节点的数值都需要更改,那么x的父节点其实就是x+lowbit(x),给出代码如下

for(i=x;i<=n;i+=lowbit(x))
{
    c[x] += v;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栖林_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值