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;
}

猜你喜欢

转载自www.cnblogs.com/wrjlinkkkkkk/p/9780894.html