首页 > 代码库 > 树状数组 小白篇(2)暨区间修改
树状数组 小白篇(2)暨区间修改
这篇主要来讲一讲树状数组的区间修改
因为一个一个点改,毫无疑问耗时太长
所以,机智的人类YY出了用差分来表示数组
为了便于理解,简单一点数组{an}:a[1]=0, a[2]=0, a[3]=0, a[4]=0, a[5]=0, a[6]=0 ,a[7]=0, a[8]=0, a[9]=0
用差分思想,delta[x]表示a[x]-a[x-1]
显然,一开始delta[]=0
我们先计算出前n项和{sn}来
然后别眨眼,下面就是见证奇迹的时刻!
有个分界线显得正式一点
我们要把a[3]到a[6]整段提高3个单位长度,就让delta[3]+=3, delta[7]-=3
想象成阶梯,一端抬起,另一端就压下去。(自行脑补)
那么现在的a[x]+=delta[1]+delta[2]+……+delta[x-1]+delta[x]
我现在要得到前7项的和,s[7]+=每一项应该加的差分
暨s[7]+=(delta[1])+(delta[1]+delta[2])+(delta[1])+delta[2]+delta[3])+……+(delta[1]+delta[2]+delta[3]+delta[4]+delta[5]+delta[6]+delta[7])
我还是画个图吧(为了方便说明只画差分的)
显然搬过砖的都知道,这个砖不好搬,因为它不方
那我们就把它变方来
(为什么那么丑,因为我不会画画以及懒)
额妹子!现在就好表示这堆砖了!!!!!!!!!
(7+1)(∑delta【1~7】)-(delta【1】*1+delta【2】*2+……+delta【7】*7)
后面的delta【n】*n很难看是不是?
那就表示成deltai【】
定义deltai【i】=delta【i】*i
显然因为要大量求和,所以我们把deltai和delta维护成树状数组
那么
1 // 修改:把[l, r]区间均加上x 2 Update(delta, l, x); 3 Update(delta, r+1, -x); 4 Update(deltai, l, x * l); 5 Update(deltai, r+1, -x * (r+1)); 6 //updata相当于上一篇的add
// 查询:[l, r]区间和 long long suml = s[l - 1] + l * Query(delta, l - 1) - Query(deltai, l - 1); long long sumr = s[r] + (r + 1) * Query(delta, r) - Query(deltai, r); ans=sumr - suml; //query相当于上一篇的sum
是不是很神奇?
感谢
“每天心塞一点点”的博客(我喜欢这个名字)
参考博文地址
树状数组 小白篇(2)暨区间修改