树状数组(小白)

树状数组(小白)

树状数组(BIT)是一种利用树的2进制特征进行检索的树状结构。树状结构是一种奇妙的数据结构,不仅非常高效,而且代码十分简洁(比线段树的代码要短且更易理解,但是可以解决的问题也是有限的,没有线段树那么广泛)
这这个大圆就相当于线段树能解决的问题,小圆就是树状数组能解决的问题,一般来说能用树状数组解决的就优先用树状数组

树状数组的概念

树状数组就是用来 动态的求前缀和·(代码的时间复杂度在log n之内)
一般来说就是两个操作 :1.单点修改 2.区间查询(通俗来说就是给某个位置上的数加上一个数;求前缀和)
当然平时做题的时候也不止这两种操作 比如有1.区间修改 2.单点查询 或者 1.区间修改 2.区间查询
(这几种操作本质上还是用树状数组解决 只不过是需要用到差分 将它转化为最初的两个操作)

下面开始举一个例子

长度为n的数列{a1,a2.....,an},进行以下操作。
(1) 修改元素add(k,x);ak(ak为数列中第k个数)加上x;2)求和sum(x):x<=n,sum=a1+a2.....+ax;
那么区间和ai+.....+aj=sum(J)-sum(i-1).

这个程序很好写,用循环加或者前缀和,复杂度是O(n).但是,如果n很大的话,这样做的效率会非常低。所以我们需要掌握树状数组。

先看代码:

int lowbit(int x){
return x&-x;
}
void add(int x,int v){  //更新数组tree[]. ax=ax+d,修改跟ax有关的tree[]
for(int i=x;i <=n;i +=lowbit(i)) tree[i] +=v;
}
int sum(int x){ //求和:sum=a1+a2....+ax
int res=0;
for(int i=x;i >0;i -=lowbit(i)) res +=tree[i];
return res;
}

add()和sum()的复杂度都是O(log2 n).(打不出来这个东西 😂)
在理解上述代码的之前 先看我下面这张图
在这里插入图片描述
这张图就是解释了add()构建tree[]数组 tree[1]=a[1] tree[2] =a[1] +a[2]; tree[3] =a[3] tree[4] =a[1]+a[2]+a[3] … 连线就代表此时tree[x]的值为那些连线位置的和
可是为什么是这些值呢
这就要看这个神奇的操作了 lowbit(x) .lowbit(x)=x&-x,功能是找到x的二进制的最后一个1.其原理是利用负数的补码表示,补码是原码取反加一。例如x=6=00000110,-x=x补=11111010,
那么lowbit(x) =x&-x=10(2进制)=2;
仔细观察就会发现 让补码与原码一一对应 以x的2进制的最后一个1为中心 原码和补码左边的部分是刚好相反的 所以在对x&-x操作时 前面的部分都为0 0&0 当然也为0 所以x&-x=10(2进制的)=2;
是不是很妙
lowbit(x)有什么用呢?
在求和计算和tree[]数组的更新都可以通过lowbit()完成。
借助tree[]数组求sum,例如:
sum[8] =tree[8];
sum[7]=tree[7]+tree[6]+tree[4];
sum[9]=tree[9] +tree[8];
那如何得到上面的关系呢
对tree[]的查找可以通过lowbit(x)实现。例如sum[7]=tree[7]+tree[6]+tree[4];
首先从7开始,加上tree[7] ;
然后7 - lowbit(7)(值为1) =6 再加上tree[6] ;
然后6 - lowbit(6)(值为2) =4 再加上tree[4]
最后4 - lowbit(4) (值为4) =0,结束;

关于tree[ ]数组的更新
当你改变a[x]的值 加个3 tree[]数组的值也应当变化 这个也使用了lowbit(x)
例如 当你改变a[6]的值后
对于tree[]数组来说肯定是6以后的位置收到影响 所以
tree[6] +=3; 然后 6 +lowbit(6) =8;
tree[8] +=3; 然后8 +=lowbit(8) =16;
以此类推 直到tree[n];
所以add() 也是用的这种方法 来初始化tree[]数组

forint i;i<=n ;i ++add(i,a[i]);
这样就是对tree[]数组进行初始化

*这里需要注意一下树状数组的下标起始一定是从1开始 如果题目下标有0的话 可以进行加1处理

说了这么多 应该都懂了树状数组了吧
接下来就开始 实战演练了 帮助你巩固 加强理解

这是树状数组的一道模板题 直接套就可以了(https://www.luogu.com.cn/problem/P3374)

然后关于树状数组较难的题 我也还在学习中😂 以后遇到会加进去的
那就先这样吧 本人小白 如有错误欢迎各位大佬指正
//南昌理工学院ACM集训队

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值