一、一维前缀和概念
定义 :
前缀和从数学上来讲就是一个数列(数列是以正整数集为定义域的一列有序的数)的前n项和。
构成:
通过数组分别保存前1项前缀和、前2项前缀和、前3项前缀和......组成前缀和数组。
二、一维前缀和例题:acwing前缀和
题干:
输入输出与数据范围:
前缀和核心代码:
前n项和 = 前n - 1项和 + 第n项
int sum[N];
for(int i=1;i<=n;i++)
{
cin>>sum[i];
sum[i]=sum[i]+sum[i-1];
}
前缀和题解:
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int sum[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>sum[i];
sum[i]=sum[i]+sum[i-1];
}
while(m--)
{
int l,r;
cin>>l>>r;
cout<<sum[r]-sum[l-1]<<'\n';
}
return 0;
}
三、二维前缀和概念
概念:
二维前缀和是一维前缀和的升级,一维前缀和表示了一段区间的和,那么二维前缀和就表示了一个二维矩阵的和。
构成:
一维前缀和使用一维数组保存,那么二维前缀和自然使用二维数组保存。
四、二维前缀和例题:acwing子矩阵的和
题干:
输入输出与数据范围:
核心代码:
思路讲解:
s[i][j]表示了从原矩阵左上角(1,1)到(i,j)的一个小矩阵的和。
如图所示:s[3][3] = s[2][3] + s[3][2] + 原矩阵[3][3] - s[2][2]
显然红色区域重复了一次,因此需要减去多余的部分。
代码展示:
int s[N][N];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&s[i][j]);
s[i][j] += s[i][j-1] + s[i-1][j] - s[i-1][j-1];
}
}
题解代码:
#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int s[N][N];
int main(){
int n,m,q;
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&s[i][j]);
s[i][j] += s[i][j-1] + s[i-1][j] - s[i-1][j-1];
}
}
while(q--)
{
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
cout<<s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1-1]<<endl;
}
return 0;
}