什么是树状数组?
用数组模拟树形结构。
可以解决的问题
每次随机给一个数加上一个增量 d e l t a delta delta,随机求区间 [ l , r ] [l,r] [l,r]的和,即 ∑ i = l r a i \sum_{i=l}^ra_i ∑i=lrai
各种各样的区间问题。
树状数组能解决的,线段树都能解决,只不过有时树状数组的常数很小,所以对于有些问题可以踩爆线段树(滑稽保命)。
时间?
修改和查询都为 O ( log 2 n ) O(\log{2}{n}) O(log2n)的复杂度。
开始推求和公式。
看这位 d a l a o dalao dalao的blog可以发现一些有趣的规律。
具体数组名称还请看dalao的blog。
不妨自己手胡一个函数 k ( i ) = i 在 二 进 制 下 从 最 低 位 到 最 高 位 连 续 0 的 长 度 k(i)=i在二进制下从最低位到最高位连续0的长度 k(i)=i在二进制下从最低位到最高位连续0的长度
得
c i = a i − 2 k ( i ) + 1 + a i − 2 k ( i ) + 2 + . . . + a i c_i=a_{i-2^{k(i)}+1}+a_{i-2^{k(i)}+2}+...+a_i ci=ai−2k(i)+1+ai−2k(i)+2+...+ai
(不要问我怎么得到的,白嫖的,不知道怎么证)
设
s u m i = ∑ j = 1 i a j sum_i= \sum_{j=1}^ia_j sumi=∑j=1iaj
得
s u m i = c i + c i − 2 k ( i ) + c i − k ( i ) − 2 k ( i − k ( i ) ) + c i − k ( i ) − k ( i − k ( i ) ) − 2 k ( i − k ( i ) − k ( i − k ( i ) ) ) + . . . sum_i=c_i+c_{i-2^{k(i)}}+c_{i-k(i)-2^{k(i-k(i))}}+c_{i-k(i)-k(i-k(i))-2^{k(i-k(i)-k(i-k(i)))}}+... sumi=ci+ci−2k(i)+ci−k(i)−2k(i−k(i))+ci−k(i)−k(i−k(i))−2k(i−k(i)−k(i−k(i)))+...
式子逐渐混乱
同样是白嫖的
一直加到不能加为止。
于是又白嫖一个等式:
2 k ( i ) = 2^{k(i)}= 2k(i)=i&(-i)
甚至毒瘤的珂学家取 2 k ( i ) 2^{k(i)} 2k(i)为 l o w b i t lowbit lowbit.
重头戏:单点修改与区间查询
更新一个 a i a_i ai的值,那么和它对应的 c c c数组里的一些值也要同步修改。白嫖一个式子:
和 a i a_i ai有关的 c c c数组的下标: 2 i + k ( i ) 2^{i+k(i)} 2i+k(i), 2 i + k ( i ) + k ( i + k ( i ) ) 2^{i+k(i)+k(i+k(i))} 2i+k(i)+k(i+k(i)), . . . ... ...
式子逐渐混乱
修改 c c c数组既珂,时间复杂度 log n \log{n} logn级别.
区间查询
学过前缀和的都知道, ∑ i = l r a i = s u m r − s u m l − 1 \sum_{i=l}^ra_i=sum_r-sum_{l-1} i=l∑rai=sumr−suml−1
这里同理,sum是可以用 log n \log{n} logn级别的时间复杂度求出来的.
差不多可以水一个P3374了。