前缀和——(2)二维数组前缀和

前面部分我们介绍了一维前缀和https://blog.csdn.net/justidle/article/details/103524440。下面我们扩展一下,来介绍二维前缀和。

什么是二维前缀和

比如我们有这样一个矩阵a,如下所示:

1 2 4 3
5 1 2 4
6 3 5 9

我们定义一个矩阵sum,其中sum_{x,y} = \sum\limits_{i=1}^x \sum\limits_{j=1}^y a_{i,j},那么这个矩阵就是这样的:

1  3  7  10
6  9  15 22
12 18 29 45

如何计算二维前缀和

求二维前缀和

假设我们需要计算(x,y)的前缀和,如下图所示。

图中我们标注出三个点。

  • 红色点表示(x,y)前缀和,用sum[x][y]表示。
  • 蓝色表示(x,y-1)前缀和,用sum[x][y-1]表示。
  • 黄色表示(x-1,y)前缀和,用sum[x-1][y]表示。
  • 紫色表示(x-1,y-1)前缀和,用sum[x-1][y-1]表示。

假设第 i 行第 j 列对应的数组为a_{i,j},对应的二维前缀和为sum_{i,j}。基于容斥原理,那么

sum_{i,j}=sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1}+a_{i,j}

样例

由于是一个非常简单的模板题,请参考以下链接http://47.110.135.197/problem.php?id=5182。也就是求二维数组对应的前缀和数组。参考代码如下:

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e3+2;
const int MAXM = 1e3+2;
int sum[MAXN][MAXM] = {};

int main() {
	int n,m,r,c;
	cin>>n>>m;//>>r>>c;
	
	int data;
	for (int i=1; i<=n; i++) {
		for (int j=1; j<=m; j++) {
			cin >> data;
			sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+data;
		}
	}
	
	for (int i=1; i<=n; i++) {
		for (int j=1; j<=m; j++) {
			cout << sum[i][j] << " ";
		}
		cout << endl;
	}
	
	return 0;
}

求范围二维前缀和

比如求(x1,y1)- (x2,y2)子矩阵的和。

sum_{x2,y2}-sum_{x1-1,y2}-sum_{x2,y1-1}+sum_{x1-1,y1-1}

下面我们用一个例子来详细说明计算过程,如下图所示:

图上有灰色、黄色、绿色和蓝色四种颜色,每个颜色表示一个区域。假设我们要求上图绿色部分的前缀和。

从图中我们可以清楚的知道,对应绿色部分前缀和为:

PrefixSum_{green} = (PrefixSum_{gray}+PrefixSum_{blue})+(PrefixSum_{gray}+PrefixSum_{yellow})-PrefixSum_{gray}+PrefixSum_{green}

假设对应坐标为(x,y)的数据前缀和用S(x,y)来表示。

整个区域。左上角为(1,1),右下角为(4,4),对应的前缀和为PrefixSum_{total} = S(4,4)

灰色区域。左上角为(1,1),右下角为(2,2),对应的前缀和为PrefixSum_{gray} = S(2,2)

黄色区域。对应的前缀和为PrefixSum_{yellow} = S(4,2)-S(2,2)

蓝色区域。对应的前缀和为PrefixSum_{blue} = S(2,4)-S(2,2)

绿色区域。对应的前缀和为PrefixSum_{green} = S(4,4) - S(4,2)-S(2,4)+S(2,2)

样例

是一个非常简单的模板题,请参考以下链接http://47.110.135.197/problem.php?id=5183

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e3+2;
const int MAXM = 1e3+2;
int sum[MAXN][MAXM] = {};

int main() {
	int n,m,r,c;
	cin>>n>>m>>r>>c;
	
	int data;
	for (int i=1; i<=n; i++) {
		for (int j=1; j<=m; j++) {
			cin >> data;
			sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+data;
		}
	}
	

	int ans = 0;
	for (int i=r; i<=n; i++) {
		for (int j=c; j<=m; j++) {
			data = sum[i][j]-sum[i-r][j]-sum[i][j-c]+sum[i-r][j-c];
			ans = max(ans, data);
		}
	}
	
	cout << ans << endl;
	
	return 0;
}
发布了138 篇原创文章 · 获赞 7 · 访问量 41万+

猜你喜欢

转载自blog.csdn.net/justidle/article/details/103754960