CodeForces - 1060C(前綴和+思維)

題意:

有一個長度爲 n 的 a 數組和長度爲 m 的 b 數組,讓這個一維矩陣相乘得到二維的矩陣,求最大子矩陣的和小於或等於 x。

題解:

有一道原題,區間範圍是1000,時間複雜度是O(n^3),用在這裏會超時。(Hihocoder 1502: 最大子矩陣

我們可以發現一個規律:一個子矩陣的和就是 (a[i]+a[i+1]+...+a[j])*(b[i]+b[i+1]+...+b[j])。

所以我們可以使用前綴和求一個子矩陣的和,我們要求的是子矩陣的大小,所以設一個數組存長度爲 1...n 的 a 和 b 的前綴和,再遍歷求最大的大小。

#include <algorithm>
#include  <iostream>
#include   <cstdlib>
#include   <cstring>
#include    <cstdio>
#include    <string>
#include    <vector>
#include    <bitset>
#include     <stack>
#include     <cmath>
#include     <deque>
#include     <queue>
#include      <list>
#include       <set>
#include       <map>
#define line printf("---------------------------\n") 
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 2000+10;

ll a[maxn], b[maxn], ma[maxn], mb[maxn];

int main(){
	int n, m;
	scanf("%d %d", &n, &m);
	a[0] = b[0] = 0;
	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];
	}
	mem(ma, inf);
	mem(mb, inf);
	for(int i = 1; i <= n; i++){
		for(int j = i; j <= n; j++){
			ma[j-i+1] = min(ma[j-i+1], a[j]-a[i-1]);
		}
	}
	for(int i = 1; i <= m; i++){
		for(int j = i; j <= m; j++){
			mb[j-i+1] = min(mb[j-i+1], b[j]-b[i-1]);
		}
	}
	ll x;
	scanf("%lld", &x);
	int ans = 0;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			if(ma[i]*mb[j] <= x){
				ans = max(ans, i*j);
			}
		}
	}
	printf("%d\n", ans);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章