差分与前缀和

article/2025/10/1 23:55:08

目录

前言

         一、算法原理

二、算法图解

三、算法模板

四、算法应用

 

前言

 

      天梯赛和省赛快开始了,不想拖后腿,边更边学习吧。

      酝酿好久的第一篇博客,缺点不少,多多指教吖。

      点赞鼓励一下吧,亲。😙😙

 

 

正文

 

一、算法原理

 

   差分和前缀和算法的核心或可浓缩成以下等式:

                               a[i]=s[i]-s[i-1]

   它是利用差分数组和前缀和数组的对应关系,改变其中之一,而影响另一的算法。差分与前缀是两个相反的过程,其中差分旨在以递推的形式记录数组元素,前缀和是以求和的方式灵活地面对区间询问。前缀和可以理解为数学中数列的前n项和,而差分则是其逆过程。

前缀和数组:用以存储已知数组的前n项和,设为s,其中s[i]存放已知数组的前i项和。                              

差分数组:用以存储已知前缀和数组的各个项,设为a,其前i项和为已知数组的第i项。

因此,差分与前缀和的关键是构造前缀和数组或差分数组。

 

 

二、算法图解

   差分与前缀和是针对数组的算法,而数组又分为一维与多维,因此差分与前缀和也包括一维与多维两种(因二维最为常见,故本篇只讨论二维),不过二者原理相同,形变神不变。

 

  • 一维前缀和

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDkuqbmnKjkuI1lbW8,size_20,color_FFFFFF,t_70,g_se,x_16

 不难看出,一维的前缀和可理解为前n项和,因此得到一维前缀和的预处理公式:                                                  ·                       a[i]=s[i]-s[i-1]

 

  • 二维前缀和

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDkuqbmnKjkuI1lbW8,size_20,color_FFFFFF,t_70,g_se,x_16

从图中我们很容易看出,整个外围蓝色矩形面积s[i][j] = 绿色面积s[i-1][j] + 紫色面积s[i][j-1] - 重复加的红色的面积s[i-1][j-1]+小方块的面积a[i][j];

因此得出二维前缀和预处理公式

s[i] [j] = s[i-1][j] + s[i][j-1 ] + a[i] [j] - s[i-1][ j-1]

 

 

  • 一维差分

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDkuqbmnKjkuI1lbW8,size_20,color_FFFFFF,t_70,g_se,x_16

 让[L,R]区间的每个元素都加一,可以构造差分数组b[]。作b[l] + c,效果使得a数组中 a[l]及以后的数都加上了c(红色部分),但我们只要求l到r区间加上c, 因此还需要执行 b[r+1] - c,让a数组中a[r+1]及往后的区间再减去c(绿色部分),这样对于a[r] 以后区间的数相当于没有发生改变。

因此我们得出一维差分结论:给a数组中的[ l, r]区间中的每一个数都加上c,只需对差分数组b做 b[l] + = c, b[r+1] - = c。时间复杂度为O(1), 大大提高了效率。

 

  • 二维差分

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDkuqbmnKjkuI1lbW8,size_20,color_FFFFFF,t_70,g_se,x_16

用数组c存储总改变量。在c[x1][y1]处加上a,在c[x2+1][y1]和c[x1][y2+1]处减a,在c[x2+1][y2+1]再加上a。最后(i,k)位置上的数值就是c数组在(i,k)位置的前缀和。c即为构造的差分数组。

 

三、算法模板

 

一维前缀和

#include<bits/stdc++.h>
using namespace std;
int main () 
{   int a[100001],sum[100001];int i,j,k,p,n,q;cin>>n>>q;for(i=1;i<=n;i++)cin>>a[i];for(i=1;i<=n;i++)      //求前缀和数组 sum[i]=sum[i-1]+a[i];while(q--)             //进行q次询问并输出 { cin>>k>>p;cout<<sum[p]-sum[k-1]<<"\n";	}	
}

二维前缀和

#include<bits/stdc++.h>
using namespace std;
int main()
{  int a[100][100],s[100][100],i,j,k,x1,y1,x2,y2,n;cin>>n>>m;for(i=1;i<=n;i++)  for(j=1;j<=m;j++){ cin>>a[i][j];s[i][j]=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];} cin>>x1>>y1>>x2>>y2;cout<<s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+a[x1-1][y1-1];}

一维差分

#include<bits/stdc++.h>
using namespace std;
int main () 
{   int a[100001],b[100001];int i,l,r,c,p,n,q;cin>>n>>q;for(i=1;i<=n;i++)   //求差分数组 { cin>>a[i];b[i]=a[i]-a[i-1];} while(q--)         //进行q次询问 { cin>>l>>r>>c;b[l]=b[l]+c;b[r+1]=b[r+1]-c;}for(i=1;i<=n;i++)  //输出改变后的数组 { b[i]=b[i]+b[i-1];cout<<b[i]<<" ";}
}

二维差分

#include<bits/stdc++.h>
using namespace std;
int main()
{  int n,m,a[100][100],s[100][100],i,j,x1,y1,x2,y2;cin>>m>>n;for(i=1;i<=m;i++) for(j=1;j<=n;j++) cin>>s[i][j];cin>>x1>>y1>>x2>>y2;a[x1][y1]++;a[x2+1][y2+1]--;for(i=1;i<=m;i++) for(j=1;j<=n;j++) a[i][j]=s[i][j]-s[i][j-1]-s[i-1][j]+s[i-1][j-1];for(i=1;i<=m;i++) for(j=1;j<=n;j++) if(j==n) cout<<s[i][j]<<"\n";else cout<<s[i][j]<<" ";
}

 

四、算法应用

前缀和

https://leetcode-cn.com/problems/subarray-sum-equals-k/

不同方法的时间复杂度:

1 暴力解法: O(n^3) 
2 前缀和方法: O(n^2)
3.前缀和+hash优化 :  O ( n )                                             因此前缀和可以对程序进行有效的优化。


差分

https://leetcode-cn.com/problems/car-pooling/

差分的应用上,可能需要稍微结合理论知识点想想,相信你做了这个典型题目,就会对差分有一个比较清晰的认知。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


http://chatgpt.dhexx.cn/article/mF4DT3ry.shtml

相关文章

算法设计 - 前缀和 差分数列

一维数组前缀和的概念 前缀和的概念很简单&#xff0c;我们用一维数组的前缀和来举例&#xff0c;有如下一维数组&#xff1a; arr [1, 2, 3, 4, 5] 该数组的前缀和数组如下 preSum [1, 3, 6, 10, 15] 关系如下&#xff1a; preSum[0] arr[0]preSum[1] arr[0] arr[1]pre…

python 前缀和总结

前缀和是数据结构与算法中比较重要的知识&#xff0c;前缀和经常可以结合哈希表解决很多有意思的问题。为了方便学习&#xff0c;在这里总结leetcode中出现的前缀和问题。 525. 连续数组 给定一个二进制数组 nums &#xff08;只含有0&#xff0c;1&#xff09;, 找到含有相同…

【c++入门(2)】前缀和

大纲 1.计算前缀和 2.计算字段和 3.后缀和 4.前缀积 5.后缀积 6.例题 1.计算前缀和 基础问题&#xff1a; 思路1&#xff1a; 枚举 cin (); for (int i 1; i < q; i) {cin >> x;int sum 0;for (int j 1; j < x; j){sum a[j];}cout << sum << endl…

前缀和

【前缀和】 什么是前缀和&#xff1f;前缀和是一个数组的某项下标之前(包括此项元素)的所有数组元素的和。 设b[]为前缀和数组&#xff0c;a[]为原数组&#xff0c;根据这句话可以得到前缀和的定义式和递推式&#xff1a; 定义式递推式一维前缀和 二维前缀和 【一维前缀和】…

Java前缀和算法

一.什么是前缀和算法 通俗来讲&#xff0c;前缀和算法就是使用一个新数组来储存原数组中前n-1个元素的和&#xff08;如果新数组的当前元素的下标为n&#xff0c;计算当前元素的值为原数组中从0到n-1下标数组元素的和&#xff09;&#xff0c;可能这样讲起来有点抽象&#xff0…

基础算法——前缀和详解

秋名山码民的主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f64f;作者水平很有限&#xff0c;如果发现错误&#xff0c;一定要及时告知作者 前言 由于有些读者朋友私聊我&#xff0c;希望出几期基础算法的讲解&#xff0c;kmp&…

前缀和算法

文章目录 前言一、关于前缀和二、一维数组求前缀和1.求段区间前缀和2.例题&#xff1a;AcWing795. 前缀和AC代码 三、二维数组求前缀和1.求S[i,j]2.求&#xff08;x1&#xff0c;y1&#xff09;&#xff0c;&#xff08;x2&#xff0c;y2&#xff09;子矩阵的和3.例题&#xff…

前缀和详解

目录 前缀和概念前缀和代码前缀和例题题目介绍思路分析相关代码 总结 前缀和概念 前缀和&#xff1a;顾名思义&#xff0c;是要求前缀的总和&#xff0c;什么是前缀&#xff0c;对于一个存放数字的数组而言&#xff0c;前缀就是指的数组的前k项&#xff0c;因此对应的前缀和就…

前缀和与差分 图文并茂 超详细整理(全网最通俗易懂)

目录 1、前缀和2、前缀和算法有什么好处&#xff1f;3、二维前缀和4、差分5、一维差分6、二维差分 1、前缀和 前缀和是指某序列的前n项和&#xff0c;可以把它理解为数学上的数列的前n项和&#xff0c;而差分可以看成前缀和的逆运算。合理的使用前缀和与差分&#xff0c;可以将…

算法:解数独

题目内容 编写一个程序&#xff0c;通过已填充的空格来解决数独问题。 一个数独的解法遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 本题满足以下设定&#xff1a; …

算法_回溯_解数独

文章目录 解数独1.解法2.总结python算法 解数独 leetcode链接 1.解法 这道题是一个棋盘问题&#xff0c;而棋盘问题是一个典型的回溯问题。 首先思考普通人&#xff08;这里指没有受过专业训练的人&#xff09;解数独的方法&#xff0c;那就是首先在空白位置假设一个数字&a…

Java编程实战12:解数独

目录 解数独题目示例 1提示 解答解题思路完整代码 解数独 题目 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内…

使用java解数独

说明 先根据规则解数独, 规则1: 如果备选数字只有一个, 那么就填入这个数字规则2: 如果在3*3单元格中, 或者一行, 或者一列中, 某个备选数字在所有的备选数字中只出现了一次, 那么就填入这个数字. 再暴力破解数独, 依次填入备选数字, 如果不能解开, 换下一个备选数字, 直到数独…

力扣 37. 解数独

一、题目描述 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。数独部分空格内已填入了数字&#xf…

LeetCode算法 —— 解数独

题目如下所示&#xff1a; 编写一个程序&#xff0c;通过已填充的空格来解决数独问题。 一个数独的解法需遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 ‘.…

C语言——解数独程序[源码]

用C语言写的解数独的程序。在linux下测试成功运行。 效果如图&#xff1a; 这是带解的数独&#xff0c;需要填写的部分用数字0代替。 这是程序运行后的效果图。看看&#xff0c;数独已经搞定啦&#xff5e;&#xff5e;&#xff5e; 程序源码如下&#xff1a; #include <…

用 Python 解数独(Sudoku)

芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独。数独是 9 横 9 竖共有 81 个格子&#xff0c;同时又分为 9 个九宫格。规则很简单&#xff1a;每个空格填入 1~9 任意一个数字&#xff0c;需要保证每个横排和竖排以及九宫格内无相同数字。 解数独是一个可有可…

解数独c++

解数独 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 数…

MATLAB 解数独

数独是一种较为常见的游戏&#xff0c;一般有4乘4、6乘6、9乘9几种&#xff0c;就像下面这种&#xff0c;本文也是主要求解此类数独。 此外还有一些奇形怪状的&#xff0c;如下图两种&#xff0c;均是不规则的&#xff0c;在此并不会涉及&#xff0c;但会在以后发布代码以及过程…

Leetcode 解数独

解数独 题目描述&#xff1a; 编写一个程序&#xff0c;通过填充空格来解决数独问题。一个数独的解法需遵循如下规则&#xff1a;数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。提示&#xff1a;…