关于树状数组的一些思考

在写题时看到大佬们对树状数组的精妙使用,故进一步思考树状数组中的规律和信息:

存袁术数据a[],   存树状数组数据 f[]

1、观察到f [i] 一定保存了a [i] 的数据

2、观察到f [i] 前面还有i个数据

3、观察到lowbit(i)可以表示f [i]中保存数据的个数

4、观察到每次减去lowbit(i) 相当于将声明当前lowbit(i) 个数已被使用,开始使用总数减去这些数后的数

5、同理,每次加上lowbit(i)相当于找到最近的能表示至少2 * lowbit(i)个数的数

思考:减去lowbit(i)和加上lowbit(i)是否在某种意义上等价?

  事实上是等价的;

  正常的顺序我们已经看过这里不再赘述

  我们观察下面的的一次更新:

    a[100111000] = k

    a[100110000] += k

    a[100100000] += k

    a[100000000] += k

  好像正确但又和我们理解的树状数组的更新不同

    我们尝试这样去理解

    a[100111001] ~ a[100111111]这些数均为0

    而我们添加的 a[100111000] = k

    实际上是a[100111000]  = k + {a[100111001] ~ a[100111111]}

    只不过后面的都是0

   这样的话我们每次减去一个lowbit(),产生一个最近的可以保存2 * lowbit()的位置,此位置正好可以将我们新增的所有数覆盖,故将新产生的数保存到这个位置

   这样虽然我们无法得到一个保存全部数据的数,但我们可以实现从后向前进行数据的保存而要想得到全部数据则需在得到1000···000时开始每次右移1,并保存所有数据最终得到答案  

  我们可以完美的证明树状数组从前往后和从后往前是完美对称的

  太美妙了

 

posted @ 2022-10-06 21:39  ginkgozyf  阅读(36)  评论(0)    收藏  举报