哎 树状数组是个什么东西嘞?
它的英文名叫做 Binary indexed tree 翻译成中文怎么是 二进制索引树?
没错。。它确实有个小名叫二元索引树。就是一棵被人类利用的小树罢了。。
那它是用来干什么的呢?
维基百科和百度百科都这样说:其初衷是解决数据压缩里的累积频率(Cumulative Frequency)的计算问题,现多用于高效计算数列的前缀和, 区间和。它可以以的时间得到任意前缀和
,并同时支持在
时间内支持动态单点值的修改。空间复杂度
。
提取和总结一下有用的信息:高效 计算区间和/前缀和 修改区间值
(但是我看视频的时候有说到其实它应用挺多的。。但 至少现在为止对我来说有用的只有这些。小的方面看的话也就是你做算法题的时候数据太大超时。。用一下这个。大的看一下就是处理大数据上啊巴拉巴拉之类的地方可以用到。。
那树状数组的原理又是什么呢?
嗯。。看完讲解的视频。没看懂。。感觉跟以前的数学归纳法差不多。。显而易见。。由规律可得。。可以自行去b站搜索关键词:树状数组。
接下来上图(乱涂乱画= =

它虽然长得跟树不一样 但其实本质是一样的 如图可见 16存储的是[1, 16]的值 15存储的是[15]的值 14存储的是[13, 14]的值 12存储的是[9, 12]的值
那到底怎么知道一个节点存储的长度/存储的哪些数字呢
接下来引入一个知识 lowbit =>
原理:我大概也知道是什么补码啊乱七八糟的与运算啊什么的 可我确实不明白它为什么要这么做
作用:取一个数转化为二进制后最右边的1与它右边的0所组成的数
举个栗子:6 => 110 | lowbit(6) = 10 = 2
不如再举一个 9 => 1001 | lowbit(9) = 1 = 1
显而易见(笑死 上下文照应)的是 每个节点存储的区间长度就是它的lowbit得到的值 比如上面的6 lowbit计算出来的值是2 也就是它存储的区间长度是2 也就是 5 6 的值的和
好了其实最重要的还是我们怎么利用这个树状数组?
首先。计算前缀和。
直接上结论(就是不懂原理我本人):就是在二进制下每一个1的位置减1。
比如6 => 110 = 110 + 100 = 6 + 4(要求到第6个的前缀和就是求6节点和4节点的值)(6节点存储的是 6 + 5 4节点存储的是 4 + 3 + 2 + 1)
7 = > 111 = 111 + 110 + 100 = 6 + 4 + 1
然后。修改区间和。
继续上结论:在二进制下的每一个1 加 1
比如 修改了6的值以后 要修改的区间(以上图为例,最大是16)6 => 110 修改 它本身+(先最右边的1加1)1000(8)+ 继续加1 10000(16)
蓝后。上代码。
我们怎么做查询呢?
得先搞个lowbit函数
int lowbit(int x)
{
return x & (-x);
}
接下来开始做查询(但是这里的查询的起始值都是数组的开头)
// 查询数组开头到x的区间和 其中c是树状数组
int query(int x)
{
int res = 0;
while(x > 0)
{
res += c[x];
x -= lowbit(x);
}
return res;
}
然后是更新数据
void updata(int i, int k)//在第i个位置加上k
{
while(i <= n) //n表示数组的末位
{
c[i] += k;
i += lowbit(i);
}
}
哎突然停止了。。因为吃个午饭睡个午觉以后突然进入老年人的脑子了= =

被折叠的 条评论
为什么被折叠?



