題意:
有一個長度爲 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);
}