关于树状数组
Posted A-Little-Nut
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于树状数组相关的知识,希望对你有一定的参考价值。
一. 什么是树状数组?
树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。
个人拙见:其实呢,是一种长的像树的可以高效查询子数组的和以及可以修改元素的数组。
二. 究竟该如何去实现它的功能呢?(以下是来自一个小白的认知,如有错误,不吝指正)
首先呢,A[]是一个数组,如果叫你求A的任意子数组的和,有个聪明的办法就是在读入A的数据时,创建数组B,B[i]是从A[0]到A[i]的和,然后呢,求子数组的和时就可以利用B数组的两个元素相减求得子数组的和, 就目前为止,该办法没什么毛病,可是呢,问题很快来了,如果A的元素会被修改呢,那数组B就要随之改变啊,如果A[i]改变,则B[i]以后的所有元素都要改变。那么树状数组可以避免去改变数组B吗,答案是NO,那为什么还用树状数组呢,因为他依然要改变B,但它改变的项会远远小于前面的做法。
说到现在,才开始进入正题,如果我们依旧沿着前面的思路,创造一个数组C,但在这里C[i]不在是A[0]到A[i]的和了
看一下上面的图,
如果
int
lowbit(
int
x){
return
x&-x;
}
其中x是表示Ax发生变化,v表示Ax发生的变化。
那么如何求sum[i]呢(sum[i]表示A[0]到A[i]的和)
比如sum[7]=(A[7])+(A[6]+A[5])+(A1 + A2 + A3 + A4)=C7+C6+C4
规律跟上面差不多,反过来的,sum[i]=Ci+sum[i-lowbit(i)];
用代码实现
int getsum(int x) {
以上是关于关于树状数组的主要内容,如果未能解决你的问题,请参考以下文章