树状数组进阶篇(区间修改、区间求和)

找到一个通俗易懂的教程,但是有点bug,在这里纠个错,顺便mark一下。

转自:点击链接

从前有个东西叫树状数组,它可以轻易实现一些简单的序列操作,比如单点修改,区间求和;区间修改,单点求值等.

但是我们经常需要更高级的操作,比如区间修改区间查询.这时候树状数组就不起作用了,只能选择写一个老长的线段树交上去结果被卡常-----而对于号称简洁ZKW线段树,区间修改反而更是噩梦一样的存在.

再但是...谁告诉你树状数组不能区间修改区间求和?告诉你,树状数组不仅能实现,而且代码依旧那么短小精悍.

今天我们就来研究研究,如何实现这个更划算的数据结构.

 

配合例题:POJ3468 A Simple Problem with Integers 加强理解。


我们已经学会了树状数组的基本操作:单点修改区间查询,或区间修改单点查询(不会的话先去自学吧...这篇文章不适合你...).思考,区间修改单点求值是怎么做到的?只需要维护一个新数组c[i]=a[i]-a[i-1],也就是c[]是a[]的差分数组,修改区间[l,r]+v只需

add(l,v);add(r+1,-v)

即可.求某个值的时候,只需要把差分数组的前缀和求出来,就是要求的了.
领悟了这个操作以后我们发现,化区间为单点的思想精髓就在于差分二字.利用差分思想,区间修改解决了,接下来就是区间求和公式的推导过程:
sum(1,n)
=a[1]+a[2]+a[3]+...+a[n-1]+a[n]
=c[1]+(c[1]+c[2])+...+(c[1]+c[2]+...+c[n])
=n(c[1]+c[2]+...+c[n])-(0c[1]+1c[2]+2c[3]+...+(n-1)c[n]).
发现什么了?
我们开第二个树状数组c2,令c2[i]=c[i]*
(i-1),那么...

区间修改[l,r]+=v:
add(c[l],v),add(c[r+1],-v);
add(c2[l],(l-1)v),add(c2[r+1],-rv);

求前缀和sum(1,n):
sum(1,n)=n*query_c(n)-query_c2(n).

求区间和sum(l,r):
sum(l,r)=sum(r)-sum(l-1).

至此,树状数组已经轻松实现了区间修改区间求和!

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值