CF C. Maximum Subrectangle【贪心 + dp】

http://codeforces.com/contest/1060/problem/C

给你一个两个数组  分别n , m 长度

然后给你n个数  m个数   一个x

然后这n + m个数 构成一个矩形

比如

3 3  

1 2 3 

1 2 3

表:就是for(i=n个数) for (j=m个数) i*j

1 2 3

2 4 6

3 6 9

再通俗点说 n = 2  m = 2

a b                     ac   ad

c d                     bc   bd       有没有发现跟乘法分配律很像

然后想到前缀和   a    (a + b)

                            c     (c + d)

然后可以发现 前缀和之乘 就是块的和

题目要求输出的是 那些块(里面数的和 小于等于x)然后输出最大块的面积

可以发现 1面积  2面积 3面积 4面积。。。。每种类型都好多 比如3*3的  1面积就有9个  4面积就有4个

一开始打算 把所有的都扫一边  看了一下会超时

然后我就想  那个结论,我只要拿一个数组保存  每一段长度为1 为2  为3 。。。的区间和 最小的值

最后直接扫n(有1长度 2长度。。n长度    n个) * m(同理)个矩形不就好了


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

#define inf 0x3f3f3f3f
const int maxn = 2100;
int a[maxn], b[maxn], Mina[maxn], Minb[maxn];
int main(){
	int n, m;
	a[0] = b[0] = 0;
	while (~scanf("%d%d", &n, &m)){
		//前缀和 
		for (int i = 1; i <= n; ++i){
			scanf("%d", &a[i]);
			a[i] += a[i - 1];
		} 
		for (int i = 1; i <= m; ++i) {
			scanf("%d", &b[i]);
			b[i] += b[i - 1];
		}
		int x;
		scanf("%d", &x);
		memset(Mina, inf, sizeof(Mina));
		memset(Minb, inf, sizeof(Minb));
		//printf("%d", Mina[1]);
		//Mina Minb 下标 是长度 
		for (int i = 1; i <= n; ++i){
			for (int j = 0; j < i; ++j){
				Mina[i - j] = min(Mina[i - j], a[i] - a[j]);
			}
		}
		for (int i = 1; i <= m; ++i){
			for (int j = 0; j < i; ++j){
				Minb[i - j] = min(Minb[i - j], b[i] - b[j]);
			}
		}
		
		int ans = 0;
		for (int i = 1; i <= n; ++i){
			for (int j = 1; j <= m; ++j){
				//会爆 
				//if (Mina[i] * Minb[j] <= x){
				if (Minb[j] <= x / Mina[i]){
					ans = max (ans, i * j);
				}
			}
		}
		printf("%d\n", ans);
		
	}
	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/liangnimahanwei/article/details/82940489