目录

三、前缀和与差分

3.1 前缀和

3.1.1 一维前缀和的算法思想

3.1.2 一维前缀和的代码实现

3.1.3 二维前缀和的基本思想

3.1.4 二维前缀和的代码实现

3.2 差分

3.2.1 基本思想

3.2.2 代码实现

3.2.3 二维差分的基本思想

3.2.4 二维差分的代码实现


三、前缀和与差分

前缀和与差分是一堆逆运算

3.1 前缀和

3.1.1 一维前缀和的算法思想

原数组:一个长度为n的数组{a1, a2, a3 … , an}

  前缀和数组:Si = a1+a2+…+ai,S0=0

(第一个下标一定要是1,把S0定义成0,这两个都是为了方便处理边界)

 1、前缀和的作用:

能够快速地求出来原数组中一段数据的和,例如,如果想算一个数组中[l,r]的 数组的和,没有前缀和数组的话,复杂度就是O(n)的 ,如果有的话,我们就是可以直接 用 Sr - Sl-1 得到,查询的复杂度就是O(1), 但是求一个前缀和数组的复杂度就是O(n),适用于输入一组数据,让求好几段的数据的和的情况,

2、如何求Si?

( 可以用for循环 递推遍历一遍,S[i] = S[i-1]+ai)

3.1.2 一维前缀和的代码实现

#include <iostream>
using namespace std;const int N = 100010;int q[N];
int s[N];int main(){int n, m;scanf("%d %d", &n, &m);for(int i = 0; i < n; i++){scanf("%d", &q[i]);}s[0] = 0;// 构造前缀和数组for(int i = 1; i <= n;i++){s[i] = s[i-1] + q[i-1];}int l, r;while(m--){scanf("%d %d", &l, &r);printf("%d\n", s[r]-s[l-1]); //区间相减}return 0;
}

3.1.3 二维前缀和的基本思想

二位前缀和,画个图 如下所示:

1、如何求某区间的和?

想要求x1, x2, x3, x4所围成的小矩形 的和,就可以用,Sx2y2 - Sx1y2 - Sx2y1 + Sx1y1

    2、如何求一个Si j

可以用两层for循环进行遍历,S[i][j] = S[i-1][j] +S[i][j-1] -S[i-1][j-1]+aij

所以定义S0=0,然后第一数都从1开始,就可以避免边界问题

3.1.4 二维前缀和的代码实现

#include <iostream>
using namespace std;const int N= 1010;int q[N][N];int main(){int n, m, qn;scanf("%d %d %d", &n, &m, &qn);//一定要从1开始,不然边界问题好难处理for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){scanf("%d", &q[i][j]);}}int s[N][N];// 构建前缀和for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){s[i][j] =s[i-1][j] + s[i][j-1]-s[i-1][j-1]+q[i][j]; }}int xa, ya, xb, yb;//区间更新while(qn--){scanf("%d %d %d %d", &xa, &ya, &xb, &yb);printf("%d\n", s[xb][yb] - s[xa-1][yb] -s[xb][ya-1] +s[xa-1][ya-1]);}return 0;
}

3.2 差分

差分是前缀和的逆运算

3.2.1 基本思想

数组:一个长度为n的数组{a1, a2, a3 … , an}

构造 一个b 数组,{b1,b2,b3…bn}

使得 ai = b1+b2+… +bi

即 b1 = a1; b2= a2-a1; b3 = a3-a2, … , bn = an-an-1

b 就是a 的差分,a就是b 的前缀和

 1、差分数组的作用:

也就是在O(n)的时间, 通过 b 差分数组 可以还原出他的 前缀和数组 a ,运用 差分的思想 可以很好的解决一类问题:

例如给定一个区间 [l, r]  让a数组,这里边所有的数都加上c,如果是用遍历,那就需要O(n)的复杂度

如果用差分来做,就可以做到O(1)原理如下:

因为 ai = b1+ b2 + …+ bi

所以只需要对 b[l] 做 +c 的操作,那 a[l] 往后的数都会 +c

又因为题目要求,只是 [l, r] 的区间,所以在对b[r+1] 做-c 的操作,相抵消,那 a[r+1] 之后的数就不会加上c了,

这样再用b数组求前缀和,还原出的a数组 就是最后的结果

所以只需要O(1)的时间就可以实现,以空间换时间

2、如何拥有差分数组呢(初始化)

其实不要考虑 差分数组 的构造,换个角度考虑从0开始用bn 生成an,这样an生成之后,b数组出来了,具体思路如下:

可以先想象a 全部都是0,那么b  也全部都是

然后怎么样变成{a1, a2, a3 … , an}呢

就是相当于 每个地方,进行了加上这个数的操作

就[1,1] 的区间+a1, [2, 2]的区间+a2 …[n, n]的区间+an

这样生成 an  和 完成题目的an 某区间+c 操作,就都可以用同样的代码段了。

3.2.2 代码实现

#include<iostream>using namespace std;const int N = 100010;int a[N],b[N];//在某区间插入某个数,以得到差分数组和前缀和数组
int insert( int l, int r, int c){b[l] = b[l]+c;b[r+1] = b[r+1] -c;
}int main(){int n, m;scanf("%d %d", &n, &m);int c;//假设本身数组a全是0, 那其差分数组也是全0//然后一个个给两个数组插入数据,例如在[1,1] 加上a1,调用insert函数//注意边界,最好从1开始,不然边界超级难处理for(int i = 1; i <= n; i++){scanf("%d", &c);a[i] = c;insert( i, i, c); //意思就是从i 到i这个区间上的数字 都加上c,}int l, r;//更新区间while(m--){scanf("%d %d %d", &l, &r, &c);insert( l, r, c);}//用更新后的b数组还原a数组for(int i = 1; i <= n; i++){a[i] = a[i-1] + b[i]; }//输出最终的数组for(int i = 1; i <= n; i++){printf("%d ", a[i]);}return 0;
}

3.2.3 二维差分的基本思想

思路和一维的是一样的,也不需要考虑直接构造差分数组,而是从0 进行初始化,用bn来生成an,这样b 和 a 数组就都是初始的状态,我们只需要考虑,如何更新:

1、如何更新二维差分数组

如图,在b数组对应的点进行+c 或者 -c的操作,会影响的整个a数组这个点往右及往下的区域都+c或者-c,所以如果只需要对a数组的 x1 x2 y1 y2 围成的矩形中进行+c操作,转化为对b点的操作就是

b[x1][y1] + c;    b[x2][y1] - c;    b[x1][y2]-c;    b[x2][y2]+c

3.2.4 二维差分的代码实现

#include <iostream>using namespace std;const int N = 1010; //二维数组的时候,这里不要太大,满足要求就行int q[N][N], b[N][N];void insert(int xa, int ya, int xb, int yb, int c){b[xa][ya] += c;b[xa][yb+1] -= c;b[xb+1][ya] -=c;b[xb+1][yb+1] +=c;
}int main(){int n, m, qn;scanf("%d %d %d", &n, &m, &qn);//以0开始构建数组for(int i = 1; i<=n; i++){for(int j = 1; j<=m; j++){scanf("%d", &q[i][j]);insert(i,j,i,j,q[i][j]);}}int xa, ya, xb, yb, c;//更新区间while(qn--){scanf("%d %d %d %d %d", &xa, &ya, &xb, &yb, &c);insert( xa, ya, xb, yb, c);}//生成最后的q数组for(int i = 1; i<=n; i++){for(int j = 1; j<=m; j++){q[i][j] = q[i][j-1]+q[i-1][j]-q[i-1][j-1]+b[i][j];}}//输出最终结果for(int i = 1; i<=n; i++){for(int j = 1; j<=m; j++){printf("%d ", q[i][j]);}printf("\n");}return 0;
}

写在最后:

这小节所讲的前缀和与差分,更重要的是一种思想,要明白各自适用于解决什么样的问题,可以在后续做题过程中多总结。加油

Acwing算法基础【1】基础(三)前缀和与差分相关推荐

  1. [AcWing算法基础课] 一.基础算法

    Algorithms + Data Structures = Programs. --Niklaus Wirth 本章包括排序.二分.高精度.前缀和与差分.双指针算法.位运算.离散化.区间合并等内容 ...

  2. c++算法基础必刷题目——前缀和与差分

    文章目录 前缀和与差分算法: 1.校门外的树 2.值周 3.中位数图 4.激光炸弹 5.二分 6.货仓选址 前缀和与差分算法:   前缀和与差分算法主要是为了快速求出某个区间的和,例如有一个数组a[1 ...

  3. yxc_第一章 基础算法(二)_前缀和与差分

    目录 一.一维前缀和 1.零散知识点 2.AcWing 795 二.二维前缀和 1.AcWing 796 三.一维差分 1.AcWing 797 四.二维差分 1.puts函数 2.AcWing 79 ...

  4. 算法基础(2) | 高精度、前缀和、差分

    文章目录 一.高精度 1.1 高精度加法 1.2 高精度减法 1.3 高精度乘法 1.4 高精度除法 二.前缀和 2.1 一维前缀和 2.2 二前缀和 三.差分 3.1 一维差分 3.2 二维差分 四 ...

  5. Acwing算法基础课学习笔记

    Acwing学习笔记 第一章 基础算法 快速排序 归并排序 二分查找 前缀和与差分 差分 位运算 离散化 第二章 数据结构 单链表 双链表 栈 队列 单调栈 单调队列 KMP算法 Trie 并查集 堆 ...

  6. AcWing 算法基础课第三节基础算法3 双指针、位运算、离散化、区间合并

    1.该系列为ACWing中算法基础课,已购买正版,课程作者为yxc 2.y总培训真的是业界良心,大家有时间可以报一下 3.为啥写在这儿,问就是oneNote的内存不够了QAQ ACwing C++ 算 ...

  7. AcWing 算法基础课第一节基础算法1排序、二分

    1.该系列为ACWing中算法基础课,已购买正版,课程作者为yxc 2.y总培训真的是业界良心,大家有时间可以报一下 3.为啥写在这儿,问就是oneNote的内存不够了QAQ ACwing C++ 算 ...

  8. python基础教程第三版豆瓣-数据结构与算法必读书单吐血整理推荐【附网盘链接】...

    前言:技术书阅读方法论 一.速读一遍(最好在1~2天内完成) 人的大脑记忆力有限,在一天内快速看完一本书会在大脑里留下深刻印象,对于之后复习以及总结都会有特别好的作用. 对于每一章的知识,先阅读标题, ...

  9. acwing算法基础__提高__进阶_课

    文章目录 1.排序 1.1. 快速排序--分治 1.2. 归并排序--分治 2.二分 2.2. 整数二分 2.3. 小数二分(浮点数二分) 3.高精度 4.前缀和与差分 5.双指针算法 6.位运算 7 ...

最新文章

  1. linux -- ./configure --prefix 命令
  2. Linux大文件切割命令split
  3. FTServer 1.1 发布,多语言全文搜索服务器
  4. 五十八、Vue中的计算属性,方法和侦听器
  5. GDI与OpenGL与DirectX之间的区别
  6. 岳云鹏:买128G手机仅112G可用!手机系统占用存储空间应厂商消化?
  7. Step ‘Publish JUnit test result report’ failed: No test report files were found问题解决
  8. 黑客攻击手段揭秘(转)
  9. python个人博客毕业设计开题报告
  10. (基础篇)用python实现打印节日贺卡
  11. 多卡聚合路由器和普通路由器的区别
  12. 关于“击败”团队目标的思考
  13. 【Linux 内核设计的艺术】从开机加电到执行 main 函数之前的过程
  14. U转串口时,鼠标乱动,解决办法
  15. 【苹果CMS技术教程】苹果CMSV10基础安装过程,如何拥有自己的视频网站
  16. 解决linux下.AppImage文件无法运行问题
  17. iOS 左上角的返回按钮的几种设置
  18. 金蝶8.0 的安装办法
  19. 读书百客:《郡斋雨中与诸文士燕集》赏析
  20. foss测试_FOSS – Java开发人员的最好朋友

热门文章

  1. 三星电子将在中国建芯片工厂
  2. 教学|大神建模师提供建模思路,建模步骤详细
  3. 柔性制造与计算机专业联系,柔性制造专业技术标准.ppt
  4. originlab matlab,Matlab调用Origin作图
  5. jenkins操作手册——巨详细,一篇足矣
  6. 北语信息院院长荀恩东:语言智能的核心是语义理解丨CCF-GAIR 2020
  7. Python Pickle任意代码执行漏洞
  8. VirtualBox安装Mac系统
  9. App推广经验|优派网助你了解读如何从零开始做好校园推广。
  10. Python采集某宝数据,轻松解决这个价值千元的外包项目