首页 > 学院 > 开发设计 > 正文

树状数组学习心得

2019-11-06 06:25:30
字体:
来源:转载
供稿:网友

这里的文章写得不错:http://blog.csdn.net/int64ago/article/details/7429868

这里写图片描述

从这张图片可以看出树状数组是一个二分的思想。那么它的本质是什么呢?其实是二进制数。例如6如果用二进制数来表示6=0110=4+2 , 13=1101=8+4+1 . 因此我们可以用一个c[]数组来表示管辖范围,c[13]=c[8]+c[4]+c[1]. 那么求1~13的和就不用a[1]+a[2]+…a[13]了,而是可以直接c[8]+c[4]+c[1]。

我们可以看出刚才的13是1101有8,4,1构成,倒序来写就是13=1+4+8。我们可以先把1减掉,12=4+8,再把4减掉,8=8,再把8减掉8-8=0.这样一步一步求和运算。对应的1,4,8就是末尾1对应的位置,也就是大牛博客里讲到的Lowbit=x & (-x).这里不赘言。

这里写图片描述 那么如何能把a[]数组转换为c[]数组呢?这里给大家一种构造,就是每个c[i]管辖的范围就是lowbit(i).比如c[6]的管辖范围是2,原因是lowbit(6)=0010,保留最后一个1。那么什么样的子节点对父节点有影响。其实就是它加上它的lowbit.相当于二分(形象的讲是镜像),把它另一边的数加上就是它的父节点。例如4的管辖范围为4,相当于二分镜像的另一边管辖范围,加上自己的节点标号就是父节点的值8。再如10的父节点是12.那么10管辖的范围应该是2,其实也就相当于二分镜像的另一边管辖范围,加上就是父节点的值。

lowbit//-x=取反+1

int lowbit(int x){ return x&(-x);}

构建父节点c[]

void update(int p,int x) { while(p<=n) { c[p]+=x; p+=lowbit(p); } }

区间求和

int sum(int p) { int sum=0; while(p>0) { sum+=c[p]; p-=lowbit(p); } return sum; }
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表