树状数组是十分的优雅的结构,用于解决区间求和,单点修改,树状数组和线段树很相似 ,线段树的使用范围更广,树状数组虽然可用的范围比线段树小但是它的效率比线段树高
下面就是树状数组的基本图形,首先要说明的是树状数组是个一维的数组 ,树状数组的下标是从1开始的 而不是从0开始的,我们只是利用了它的下标值的特点,来进行区间的求和,单点修改。
1 红色标注的是现在 树状数组的下标
2 每个红色标注的上方的方格内代表着树状数组能表示原来的数组( 就是要求和,修改单点的数组 )
比如 红色下标 2 上方的 (1,2) 表示了他代表的是原来数组从 a[1] 一直到a[2]的和 (假设原来的数组为 a[8])
再比如 红色下标3 上方的 (3) , 就表示他代表的是原来数组 a[3] (只有一个就不用再说求和了。。。)
看下面这个表格 ,要注意的是 树状数组巧妙地利用了 二进制数的特点 。
这个图和上边的 图是相互对应的 ,观察到一下的特点
1 . 节点下标和第四列的 最后一个元素是一样的 (就是树状数组的一个节点 所表示的范围的最后一个元素)。
2. 节点对应的元素个数是 节点下标的二进制中从右到左的0的个数 的二次方,也就是从右到左有k个0,那么能表示的
个数就是2^k , 比如1的二进制 k =0,所以它能表示的个数是2^0 (就是1个). 再比如6的二进制 0110 , k = 1所以它能表示的个数就是 2个。
3 . 每个节点所能表示的原来数组( 就是要求和,修改单点的数组 )的下标都是连续的。
一 . 在了解树状数组的这些特性之后我们来看一下 树状数组很重要的 lowbit() 这个函数
int lowbit(int x){
return x&(-x);
}
下面这个证明说的很详细
首先明白一个概念,计算机中-i=(i的取反+1),也就是i的补码