前缀和

前缀和

前缀和数组s[ ],数组a[ ]的前n项和。

如何求前缀和数组s[ ]?

核心公式:s[i] = s[i - 1] + a[i]

前缀和

作用:用于快速求出数组内一段区间[l,r]的和。如果不使用前缀和而朴素的扫描一遍,时间复杂度位O(n)。通过前缀和时间复杂度为O(1)。

区间[l,r]的和:s[r] - s[l - 1]

注意:前缀和数组的下标从1开始,并且定义S[0] = 0。这是为了公式的统一。

795 前缀和

代码

#include<iostream>
#include<cstdio>

using namespace std;

const int N = 100010;
int n,m;
int a[N],s[N];

int main()
{
	cin>>n>>m;
	for (int i = 1; i <= n; i ++ ) cin>>a[i];
	
	s[0] = 0;
	for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i];
	
	while(m--)
	{
		int l = 0,r = 0;
		cin>>l>>r;
		cout<<s[r]-s[l-1]<<endl;
	}
    return 0;
}

二维前缀和

类似上面的一维前缀和,我们有二维数组a[ ][ ]以及二位前缀和数组s[ ][ ].

如何构建二维前缀和数组呢?

前缀和

核心公式: s[x][y] = s[x-1][y] + s[x][y-1] - s[x - 1][y - 1] + a[x][y]

作用:快速求出二维数组内区间[x2,y2]到[x1,y1]和。

区间[x2,y2]到[x1,y1]的和: s[x2][y2] - s[x2][y1-1] + s[x1 - 1][y2] + s[x1 - 1][y1 - 1]

796 子矩阵的和

代码

#include<iostream>
#include<cstdio>

using namespace std;

const int N = 1010;

int n,m,q;
int a[N][N],s[N][N];

int main()
{
	cin>>n>>m>>q;
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= m; j ++ )
			cin>>a[i][j];
	
	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] + a[i][j];
	
	while(m--)
	{
		int x1 = 0,y1 = 0,x2 = 0, y2 = 0;
		cin>>x1>>y1>>x2>>y2;
		cout<<s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]<<endl;
	}
    return 0;
}

习题

前缀和

上一篇:【DP】棋盘分割


下一篇:【数据结构和算法】判断两个矩形是否相交