树状数组(区间修改,区间查询)
树状数组(区间修改,区间查询)
原创 已于 2023-12-04 19:11:20 修改 · 粉丝可见 · 1.2k 阅读 · 10 · 15 · 本内容遵循CC 4.0 BY-SA版权协议 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/134790835
本题链接: 用户登录
题目:

样例:
cobol<br/>5 5<br/>1 2 3 4 5<br/>2 1 2<br/>1 2 3 1<br/>2 1 3<br/>1 1 5 1<br/>2 1 5<br/> |
|---|
cobol<br/>3<br/>8<br/>22<br/> |
|---|

思路:
树状数组的区间修改,区间查询,操作起来有点繁琐了些,但还是可以理解的。
这里区间修改,我们还是需要需要通过差分来进行区间修改的。
不同的是,在于区间查询这一块。
我们先模拟一遍区间修改后,差分数组 dif,原数组 a
得: 差分数组的前缀和,就是获得当前原数组的数值
1 | |
而我们需要求的是区间和,所以当我们设前缀和数组为 sum可知
1 | |
所以,当我们区间查询区间求和的时候
可以得出,我们区间求和, 相应的差分求和的求和具有一定的规律性。
此时我们将其化为差分,可以得知,减去剩余的 dif[] 随即递增的累乘
1 | |
所以我们需要 两个差分数组 来进行区间修改以及区间查询。
一个 dif 为 正常的 (dif[n] + dif[n - 1] + ... + dif[1]) 的前缀和差分数组;
一个 p_dif 为 (dif[1] * 1 + dif[2] * 2 + ... + dif[n] * n)的前缀和差分数组;
还有前缀和函数 sum
最后通过前缀和相减,就可以获得区间和了
操作函数如下:
cpp<br/>// 单点修改函数<br/>inline void Add_pos(int tr[],int pos,int x)<br/>{<br/> for(int i = pos;i <= n + 1;i+=lowbit(i)) tr[i] += x;<br/>}<br/> |
|---|
cpp<br/>// 获取前缀和函数<br/>inline int getSum(int tr[],int pos)<br/>{<br/> int res = 0;<br/> for(int i = pos;i;i-=lowbit(i)) res += tr[i];<br/> return res;<br/>}<br/> |
|---|
cpp<br/>// 区间修改加值<br/>inline void Add_section(int l,int r,int x)<br/>{<br/> // 差分加值 dif<br/> Add_pos(dif,l,x);<br/> Add_pos(dif,r+1,-x);<br/> <br/> // 差分加值 p_dif<br/> Add_pos(p_dif,l,l*x);<br/> Add_pos(p_dif,r+1,(r+1)*(-x));<br/>}<br/> |
|---|
cpp<br/>// 获取 Sum 的前缀和<br/>inline int get_difSum(int pos)<br/>{<br/> // 求 sum 的前缀和函数<br/> return getSum(dif,pos)*(pos + 1) - getSum(p_dif,pos);<br/>}<br/> |
|---|
cpp<br/>// 获取区间前缀和<br/>inline int Ask_section(int l,int r)<br/>{<br/> return get_difSum(r) - get_difSum(l-1);<br/>}<br/> |
|---|
代码详解如下:
1 | |
最后提交:


觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭
wechat pay
ali pay
树状数组(区间修改,区间查询)
http://blog.angindem.cn/2023/12/04/Angindem-CSDN博客/112_112/