题干:
You are given two arrays aa and bb of positive integers, with length nn and mmrespectively.
Let cc be an n×mn×m matrix, where ci,j=ai⋅bjci,j=ai⋅bj.
You need to find a subrectangle of the matrix cc such that the sum of its elements is at most xx, and its area (the total number of elements) is the largest possible.
Formally, you need to find the largest number ss such that it is possible to choose integers x1,x2,y1,y2x1,x2,y1,y2 subject to 1≤x1≤x2≤n1≤x1≤x2≤n, 1≤y1≤y2≤m1≤y1≤y2≤m, (x2−x1+1)×(y2−y1+1)=s(x2−x1+1)×(y2−y1+1)=s, and
∑i=x1x2∑j=y1y2ci,j≤x.∑i=x1x2∑j=y1y2ci,j≤x.
Input
The first line contains two integers nn and mm (1≤n,m≤20001≤n,m≤2000).
The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤20001≤ai≤2000).
The third line contains mm integers b1,b2,…,bmb1,b2,…,bm (1≤bi≤20001≤bi≤2000).
The fourth line contains a single integer xx (1≤x≤2⋅1091≤x≤2⋅109).
Output
If it is possible to choose four integers x1,x2,y1,y2x1,x2,y1,y2 such that 1≤x1≤x2≤n1≤x1≤x2≤n, 1≤y1≤y2≤m1≤y1≤y2≤m, and ∑x2i=x1∑y2j=y1ci,j≤x∑i=x1x2∑j=y1y2ci,j≤x, output the largest value of (x2−x1+1)×(y2−y1+1)(x2−x1+1)×(y2−y1+1) among all such quadruplets, otherwise output 00.
Examples
Input
3 3
1 2 3
1 2 3
9
Output
4
Input
5 1
5 4 2 4 5
2
5
Output
1
Note
Matrix from the first sample and the chosen subrectangle (of blue color):
Matrix from the second sample and the chosen subrectangle (of blue color):
题目大意:
给出两个数组A和B,他们能组成一个矩阵,然后求子矩阵的和<=X的,最大的子矩阵的面积。
解题报告:
听说有人往滑窗问题上想了?
如果题目规定是正方形就好做了啊,二维前缀和+二分宽度,直接o(nmlog(nm)),如果矩形的话只能带俩log了。。。没尝试过。但应该也不难写。
想想啊,为什么题目不直接给你一个矩阵,而是给你俩数组让你自己造矩阵?肯定是因为矩阵只是个幌子,真正要用到的还是那两个数组。所以我们推公式:
于是我们知道了和x比较的值只与连续子段和有关,且A和B这两者之间没关系(只是最后做一下乘法)所以算出每个长度的最小和,最后再o(nm)遍历一遍维护答案就行了。
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll INF = 0x3f3f3f3f;
ll a[2005],b[2005],suma[2005],sumb[2005];
ll dpa[2005],dpb[2005];
ll x,ans;
int main()
{int n,m;cin>>n>>m;memset(dpa,INF,sizeof dpa);memset(dpb,INF,sizeof dpb);for(int i = 1; i<=n; i++) scanf("%lld",a+i),suma[i] = suma[i-1] + a[i];for(int i = 1; i<=m; i++) scanf("%lld",b+i),sumb[i] = sumb[i-1] + b[i]; scanf("%lld",&x);for(int len = 1; len<=n; len++) {for(int i = 1; i+len-1<=n; i++) {dpa[len] = min(dpa[len],suma[i+len-1] - suma[i-1]);}}for(int len = 1; len<=m; len++) {for(int i = 1; i+len-1<=m; i++) {dpb[len] = min(dpb[len],sumb[i+len-1] - sumb[i-1]);} }for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {if(dpa[i] * dpb[j] <= x) ans = max(ans,(ll)i*j);}}printf("%lld\n",ans);return 0 ;
}
网络版AC代码:(博客链接)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2000;
ll lA,lB,x;
int A[N+5],B[N+5];
struct NODE{ll len,sum;
}node[N*N+5];
int cnt_NODE;
bool cmp_NODE(NODE A,NODE B){return A.sum<B.sum;
}
int Solve(ll sum){int l=0,r=cnt_NODE-1;if(node[r].sum<=sum) return r;while(l+1<r){int mid=(l+r)>>1;if(node[mid].sum<=sum) l=mid;else r=mid;}if(node[r].sum<=sum) return r;return l;
}
int main(){scanf("%d%d",&lA,&lB);for(int i=1;i<=lA;i++)scanf("%d",&A[i]);for(int i=1;i<=lB;i++)scanf("%d",&B[i]);scanf("%d",&x);for(int i=1;i<=lA;i++){ll sum=0;for(int j=i;j<=lA;j++){sum+=A[j];node[cnt_NODE].len=j-i+1;node[cnt_NODE].sum=sum;cnt_NODE++;}}sort(node,node+cnt_NODE,cmp_NODE);for(int i=1;i<cnt_NODE;i++)node[i].len=max(node[i].len,node[i-1].len);ll ans=0;for(int i=1;i<=lB;i++){ll sum=0;for(int j=i;j<=lB;j++){sum+=B[j];if(x/sum==0) continue;int res=Solve(x/sum);if(node[res].sum>x/sum) continue;ans=max(ans,node[res].len*(j-i+1));}}printf("%lld\n",ans);return 0;
}