CF1060C题解

为了摆脱小凯的阴影,我开始刷CF上的思维题

模拟

由乘法分配律,有\(\sum_{i=x1}^{x2}\sum_{j=y1}^{y2}c_{i,j}=\sum_{i=x1}^{x2}\sum_{j=y1}^{y2}a_i*b_j=\sum_{i=x1}^{x2}a_i*\sum_{j=y1}^{y2}b_j\)

故问题转变为选取 a,b 的两个字段,使其乘积 ≤ x,且面积最大

刚开始的思路是可以\(n^2\)枚举a的所有区间,对于每个区间,若权值和为v,则在权值 <= x/v 的区间中选取长度最长的,可以用树状数组+离散化 or 动态开点权值线段树维护,复杂度\(O(N^2logN)\)

后来看了题解有一种更简单的思路,若区间长度一定,则权值越小越好,故记录长度为i的最小权值,复杂度可降至\(O(N^2)\)

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define fo(i,a) for(int i=0;i<a;++i)
#define il inline
#define int long long

const int inf=0x3f3f3f3f,N=2e3+10;

int n,m,a[N],b[N],lim,f[N],g[N];

il void read(int &x){
    x=0;char c=getchar(),f=1;
    while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); }
    while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); }
    x*=f;
}
il void gmin(int &x,int y){
    x=x<y?x:y;
}

signed main(){
    //freopen("input.txt","r",stdin);
    read(n),read(m);
    go(i,1,n) read(a[i]),a[i]+=a[i-1];
    go(i,1,m) read(b[i]),b[i]+=b[i-1];
    read(lim);
    mem(f,0x3f),mem(g,0x3f);
    go(i,1,n)
        go(j,i,n)
            gmin(f[j-i+1],a[j]-a[i-1]);
    go(i,1,m)
        go(j,i,m)
            gmin(g[j-i+1],b[j]-b[i-1]);
    int ans=0;
    go(i,1,n)
        go(j,1,m)
            if(f[i]*g[j]<=lim) 
                ans=max(ans,i*j);
    cout<<ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/White-star/p/11777781.html