CF C. Maximum Subrectangle【贪心 + dp】

本文探讨了如何使用前缀和技巧解决特定矩阵问题,通过计算不同长度区间的最小值来快速找出满足条件的最大矩阵面积,避免了遍历所有可能组合的效率低下问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给你一个两个数组 分别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;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值