树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。
首先照例附上树状数组的百度百科解释。实际上,经过“简单修改”可以做到区间修改与区间求和。树状数组,在你写线段树区间求和写的吐血的时候,是个不错的选择。
一维+单点修改+查询
这张图片在很多树状数组的讲解中都有出现过。明确,c数组是我们的树状数组,a数组是我们的基础数组。我们所有的操作都是基于c数组上的,但是事实上题目所给我们的只有a数组。
区间求和操作,实际上可以转换为维护数组前缀和的操作。由树状数组的标准解释来说,树状数组天生就是为了维护数组前缀和的。
规定add(x,addtag)操作为将a[x]加上addtag,get_sum(x)操作为求a[1]-a[x]的和。
先从get_sum()操作讲起,从图中我们可以很简单的得到,c[]可以由多个c[]及a[]得到。例如c[8]=c[4]+c[6]+c[7]+a[8]。如果我们将c[4],c[6],c[7],均表示为多个c[]及a[]的形式,最终我们会发现,我们得到c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8].
所以说get_sum(x)操作只需要输出c[x]吗?显然不是。
我们换一个例子。
c[7]=a[7],而get_sum(7)显然不等于a[7]。经过观察发现,get_sum(7)=c[7]+c[6]+c[4]。我们仔细观察这张图,会发现一些无法用言语描述的奇妙规律。(当然你也很可能会描述)只要表示出这些规律我们就完成了任务,于是我们把这些数字写成二进制。
get_sum(111