【jzoj4820】【最大化】【单调栈】

题目大意

这里写图片描述

解题思路

枚举左右边界,压成一维做前缀和,维护一个单调递减的栈,从后往前做,对答案有贡献的是小于它的最前点,如果比上一个大则继续退栈,比上一个小则不可能对答案贡献,因为和它匹配的点序号更大,区间长度更小。

code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define max(n1,n2) ((n1>n2)?n1:n2)
#define min(n1,n2) ((n1>n2)?n2:n1)
#define num(n1,n2) ((n1-1)*3*n+n2+1)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const maxn=300,inf=2147483647;
int n,m,l,r;LL x,s[maxn+10][maxn+10],sum[maxn+10],a[maxn+10],b[maxn+10];
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    scanf("%d%d",&n,&m);
    fo(i,1,n)
        fo(j,1,m)
            scanf("%lld",&x),s[i][j]=s[i][j-1]+x;
    LL ans=1;
    fo(i,0,m)
        fo(j,i+1,m){
            a[0]=0;
            fo(k,1,n){
                sum[k]=sum[k-1]+s[k][j]-s[k][i];
                if(sum[k]<a[a[0]])a[++a[0]]=sum[k],b[a[0]]=k;
            }
            fd(k,n,1)
                if(a[a[0]]<sum[k]){
                    for(;a[0]&&(a[a[0]-1]<sum[k]);a[0]--);
                    ans=max(ans,(k-b[a[0]])*(j-i));
                }
        }
    printf("%lld",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值