码蹄杯 palace 题型:二维前缀和模板题 难度:钻石

63 阅读2分钟

码题集OJ-palace (matiji.net)

image.png

样例输入:

3 2
4 0
-10 8
-2 -2

样例输出:

4

二维前缀和模板题,但是注意细节,像下面这样写有一个点超时:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 210;
int a[N][N];
int sum[N][N];
int n, m;
int ans;

signed main() {
	cin >> n >> m;
	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++) {
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i-1][j-1]+a[i][j];
		}
	}

	//求一下两个坐标构成的矩形面积
	for (int x1 = 1; x1 <= n; x1++) {
		for (int y1 = 1; y1 <= m; y1++) {
			for (int x2 = 1; x2 <= n; x2++) {
				for (int y2 = 1; y2 <= m; y2++) {
					int Sum = sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];

					if (Sum > 0)
						ans = max(ans, (x2 - x1 + 1) * (y2 - y1 + 1));
				}
			}
		}
	}
	cout << ans << endl;
	return 0;
}

image.png

我们可以加一个优化,让x2从x1开始枚举,不要从1开始枚举。也就是说x1枚举过的x2就不要去枚举了,x2一定在x1下面:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 210;
int a[N][N];
int sum[N][N];
int n, m;
int ans;

signed main() {
	cin >> n >> m;
	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++) {
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i-1][j-1]+a[i][j];
		}
	}

	//求一下两个坐标构成的矩形面积
	for (int x1 = 1; x1 <= n; x1++) {
		for (int y1 = 1; y1 <= m; y1++) {
			for (int x2 = x1; x2 <= n; x2++) {
				for (int y2 = 1; y2 <= m; y2++) {
					int Sum = sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];

					if (Sum > 0)
						ans = max(ans, (x2 - x1 + 1) * (y2 - y1 + 1));
				}
			}
		}
	}
	cout << ans << endl;
	return 0;
}

image.png