关于树状数组
来源:互联网 发布:知柏地黄丸 口腔溃疡 编辑:程序博客网 时间:2024/06/05 23:55
一、树状数组是什么?
二、树状数组怎么做的?
怎样做到不断一分为二?先说个lowbit,lowbit(k)就是把k的二进制的高位1全部清空,只留下最低位的1,比如10的二进制是1010,则lowbit(k)=lowbit(1010)=0010(2进制)。方法lowbit(k)=k&-k,这是位运算,我们知道一个数加一个负号是把这个数的二进制取反+1,如-10的二进制就是-1010=0101+1=0110,然后用1010&0110,答案就是0010。关于lowbit的用处,它是为了联系a数组和c数组的。ck表示从ak开始往左连续求lowbit(k)个数的和,c[0110]=a[0110]+a[0101],就是从110开始计算了0010个数的和,因为lowbit(0110)=0010,可以看到其实只有低位的1起作用,显然c[0010]=a[0010]+a[0001],这就为什么我们任何数都只关心它的lowbit,因为高位不起作用。
如何实现a某一个位置数据更改?比如更改了a[0011],我们接着要修改c[0011],c[0100],c[1000],其实从0011——>0100——>1000的变化都是进行“去尾”操作,又是自己造的词--'',我来解释下,就是把尾部应该去掉的1都去掉转而换到更高位的1,记住每次变换都要有一个高位的1产生,所以0100是不能变换到0101的,因为没有新的高位1产生,这个变换过程恰好是可以借助我们的lowbit进行的,k +=lowbit(k)。
为什么它是这种关系?这就要追究到之前我们说c8可以看作a1~a8的左半边和+右半边和……的内容了,为什么c[0011]会影响到c[0100]而不会影响到c[0101],这就是之前说的c[0100]的求解实际上是这样分段的区间 c[0001]~c[0001] 和区间c[0011]~c[0011]的和,数字太小,可能这样不太理解,在比如c[0100]会影响c[1000],为什么呢?因为c[1000]可以看作0001~0100的和加上0101~1000的和,但是0101位置的数变化并会直接作用于c[1000],因为它的尾部1不能一下在跳两级在产生两次高位1,是通过c[0110]间接影响的,但是,c[0100]却可以跳一级产生一次高位1。
只需注意:c的构成性质(其实是分组性质)决定了c[0011]只会直接影响c[0100],而c[0100]只会直接影响[1000],而下表之间的关系恰好是也必须是k +=lowbit(k)。
三、与线段树的对比
- 关于树状数组
- 关于树状数组
- 关于“树状数组”
- 关于树状数组
- 关于树状数组的姿势
- 关于树状数组的一个小问题
- 关于树状数组求逆序数
- 关于树状数组一些有意思的东西
- 关于树状数组的一些讨论
- 树状数组
- 树状数组
- 树状数组
- 树状数组
- 树状数组
- 树状数组
- 树状数组
- 树状数组
- 树状数组
- bzoj 3521/5083 [Poi2014]Salad Bar/普及 (卡常)st表+二分+树状数组
- 第九周 项目一 创建二叉树算法库
- 【bzoj2083】[Poi2010]Intelligence test
- webpack
- PHP读取文件的操作
- 关于树状数组
- js中this的作用域
- java随笔: Java中字符串indexof() 的使用方法
- 【NOIP模拟】 (10.26) T1 抄代码
- File
- 四种会话跟踪技术
- [RESideMenu 的设置记录一下]
- 【数据库设计】11招教你如何玩转数据库
- 串行端口 boost asio