Codeforces 1060C Maximum Subrectangle(子矩阵+预处理)
题意:给出数组a,b,组成矩阵c,其中$c_{ij}=a_i*b_j$,找出最的大子矩阵,使得矩阵元素和<=x,求这个矩阵的size
n,m<=2000
思路:对于子矩阵(l1...r1)*(l2...r2),矩阵元素和为(a[l1]+a[l1+1]+...+a[r1])*(b[l2]+b[l2+1]+...+b[r2])
这样处理出长度为i的连续数组最小和aa[i],bb[i],再枚举一下长度即可
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> //#include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 100003; const int maxn = 2e5+100; const int maxm = 2e5+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); ll a[maxn],b[maxn]; ll aa[maxn], bb[maxn]; int main() { int n, m; scanf("%d %d", &n, &m); mem(a, 0); mem(b, 0); for(int i = 1; i <= n; i++){ scanf("%lld", &a[i]); a[i]+=a[i-1]; } for(int i = 1; i <= m; i++){ scanf("%lld", &b[i]); b[i]+=b[i-1]; } ll ans = 0; ll tmp = 0; ll x; scanf("%lld", &x); mem(aa,0x3f); mem(bb,0x3f); for(int i = 1; i <= n; i++){ for(int j = 1; j <= i; j++){ //j~i aa[i-j+1]=min(aa[i-j+1],a[i]-a[j-1]); } } for(int i = 1; i <= m; i++){ for(int j = 1; j <= i; j++){ bb[i-j+1]=min(bb[i-j+1],b[i]-b[j-1]); } } for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(aa[i]*bb[j]<=x)ans = max(ans, 1ll*i*j); } } printf("%lld", ans); return 0; }