给定一个长度为 nn 的整数数组 a1,a2,…,an 和一个长度为 m 的整数数组 b1,b2,…,bm。
设 cc 是一个 n×m的矩阵,其中 ci,j=ai×bj。
请你找到矩阵 c 的一个子矩阵,要求:该子矩阵所包含的所有元素之和不超过 x,并且其面积(包含元素的数量)应尽可能大。
输出满足条件的子矩阵的最大可能面积(即包含元素的最大可能数量)。
输入格式
第一行包含两个整数 n,m。
第二行包含 nn 个整数 a1,a2,…,an。
第三行包含 mm 个整数 b1,b2,…,bm。
第四行包含一个整数 x。
输出格式
一个整数,表示满足条件的子矩阵的最大可能面积(即包含元素的最大可能数量)。
如果不存在满足条件的子矩阵,则输出 0。
数据范围
前三个测试点满足 1≤n,m≤5。
所有测试点满足 1≤n,m≤2000,1≤ai,bi≤2000,1≤x≤2×1e9。
输入样例1:
3 3
1 2 3
1 2 3
9
输出样例1:
4
输入样例2:
5 1
5 4 2 4 5
2
5
输出样例2:
1
分析:
首先我们可以将题目所求的子矩阵元素和转换为求a b数组的一段子区间和的乘积
如下如果知道这一点。后面的内容就很简单:
a1 * b1 + a2 * b1 + a3 * b1
a1 * b2 + a2 * b2 + a3 * b2 = (a1 + a2 + a3) * (b1 + b2 + b3)
a1 * b3 + a2 * b3 + a3 * b3
为了使我们的区间很大,我们就使每一个区间越小就可以了,因此我们可以求出lena[N]数组,第i个数组的值表示a区间长度为i时的最小和是多少,lenab[N]同理
区间和可以用前缀和实现
记录a b数组长度为1~n /m的最小区间和
然后暴力枚举a的区间长度和b的区间长度进行判断比较即可
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=2010;
long long a[N],b[N],lena[N],lenb[N];
long long x,sum;
int m,n;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
for(int i=1;i<=m;i++) cin>>b[i],b[i]+=b[i-1];
cin>>x;
for(int len=1;len<=n;len++)
{
long long minn=4e6+10;
for(int i=1;i<=n-len+1;i++)
{
int r=i+len-1;
minn=min(minn,a[r]-a[i-1]);
}
lena[len]=minn;
// cout<<len<<" a: "<<lena[len]<<endl;
}
for(int len=1;len<=m;len++)
{
long long minn=4e6+10;
for(int i=1;i<=m-len+1;i++)
{
int r=i+len-1;
minn=min(minn,b[r]-b[i-1]);
}
lenb[len]=minn;
// cout<<len<<" b: "<<lenb[len]<<endl;
}
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(lena[i]*lenb[j]<=x)
{
// cout<<lena[i]<<" "<<lenb[j]<<endl;
ans=max(ans,i*j);
}
}
}
cout<<ans;
}