ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于树状数组存储&修改&查询前缀和方式的正确性的证明

2021-09-11 23:02:32  阅读:171  来源: 互联网

标签:存储 前缀 覆盖 树状 lowbit 正确性 数组 一定


七月思考过的问题,突然想起来了,就写出来
才不是因为现在才发现自己写的树状数组里忘记说这个问题了呢!)(大雾)(好怪啊
(与其说是证明不如说是一个比较严谨且易懂的感性理解)
(大概..还算是严谨吧?)

不会树状数组模板的走传送门:树状数组模板整理

前置设定:a[i]为原数列,c[i]为维护树状数组所用的数组

关于存储方式:

每一个c[i]存储一段从a[i-lowbit(i)+1]到a[i]的长度为lowbit(i)的区间内的数据的和,而lowbit是每一个i在二进制下从最低位起第一个1和这个1之前的所有0组成的数,每一个i都存在lowbit值,因此c[i]存储
a[i-lowbit(i)+1]到a[i]的和,设q=i-bowbit,c[i-lowbit]存储a[q-lowbit(q)+1]到a[i-lowbit]的和......
最终,原序列a[]被所有的c[i]完整的覆盖了,即c数组完整地存储了属于a的所有数据,因此存储是具有正确性的。

关于查询方式:

由于每一个c[i]都存储一段以i为终点,向前延伸至起点i-lowbit(i)+1的长度为lowbit(i)的数组,而c[i-lowbit(i)]也具有相同性质。
从i开始,不断向1延伸,每次加上当前所到达的c[x]的值,则整段从i到1的序列的所有数都被加入了res,因此具有正确性。
(简单来说就是按照模板的方式,i1的序列会被完整地覆盖,i1的和也就被不重不漏地求出了)

关于修改方式:

关键在于:a[i]一定被c[i+lowbit(i)]覆盖了。
遇事不决,先分奇偶:
(1)若i为奇数,则根据奇数的性质:奇数在二进制下的第一位一定为1,因此lowbit(i)=1,因此i+lowbit(i)就一定是偶数,偶数在二进制下的第一位一定不为0,因此lowbit(i+1)大于等于2。
就可以发现,i与i+lowbit(i)之间的差为1,而lowbit(i+1)>=2。
即c[i+lowbit(i)]覆盖的区间长度至少为2,一定包含了i。
故得证:i为奇数时,a[i]一定被c[i+lowbit(i)]覆盖

(2)若i为偶数,则取出的lowbit(i)的大小是i的第一个1和该1前面所有的0组成的数的大小,由于进位,i加上lowbit(i)后,生成的新数lowbit(i)+i的第一个1的位置一定比i位于更高位。
即lowbit(lowbit(i)+i)一定大于lowbit(i)。
由于lowbit(i)+i与i之间的差为lowbit(i),而c[lowbit(i)+i]向下覆盖的距离lowbit(lowbit(i)+i)一定大于二者之差lowbit(i)。
同样得证:i为偶数时,a[i]一定被c[i+lowbit(i)]覆盖。

这时候已经得证了,总结一下,可以得出一个容易一些的理解:

无论i的奇偶性,c[lowbit(i)+i]覆盖的区间长度,一定大于lowbit(i)+i与i之间的差lowbit(i)。
因此a[i]一定被c[lowbit(i)+i]覆盖。

因此,想要找到所有被a[i]影响的c[i]只需不断向上累加lowbit(i),正如模板中的做法。

END

或者我们可以草率一些,直接看图也可以得出修改方式的正确性。
image
比我那一堆废话好懂多了,不是吗?

标签:存储,前缀,覆盖,树状,lowbit,正确性,数组,一定
来源: https://www.cnblogs.com/mint-hexagram/p/15257048.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有