JZOJ 4820 【NOIP2016提高A组模拟10.15】最大化

最大化

题目大意

给你一个n*m的网格,每个格子有一个数a_{i,j},现在要求一个面积最大的矩形,使得这个矩形内的平均值大于0,求最大面积。

数据范围

这里写图片描述

题解

先转化题目,平均值大于 0 也就意味着总和大于0
首先枚举这个矩形的上下边界,对于每种情况分开做。
定义 Si 表示右边界为第 i 列,左边界为第1列,上下边界确定时,该矩形的面积。
在上下边界已经确定的情况下,对于以第 j 列为右边界,我们需要找一个最小的k,满足 k < j Sk < Sj ( Sj - Sk > 0 ),此时,以第k+ 1 列为左边界的 以第j列为右边界的矩形 的面积是最大的。
那我们怎么找 k 的值呢?
考虑二分这个值,假设当前枚举的二分值为mid,若 min ( S0 , S1 , S2 Smid ) < Sj 则说明 0 ~mid内有满足条件的 k ,二分上调,反之二分下调。
min( S0 , S1 , S2 Si )可以预处理出来。
常数卡的好就可以过了。

Code(Pascal)

var
    n,m,j,k,l,i:longint;
    o,ans,le,ri,mid,u:int64;
    wz:array[-1..500] of int64;
    a,qz:array[0..300,0..300] of int64;
function min(a,b:int64):int64;
    begin
        if a<b then exit(a)
        else exit(b);
    end;
function max(a,b:int64):int64;
    begin
        if a>b then exit(a)
        else exit(b);
    end;
begin
    readln(n,m);
    for i:=1 to n do
    begin
        o:=0;
        for l:=1 to m do
        begin
            read(a[i,l]);
            o:=o+a[i,l];
            qz[i,l]:=qz[i-1,l]+o;
        end;
        readln;
    end;
    for i:=1 to n do
    for l:=i to n do
    if (l-i+1)*m>ans then
    begin
        wz[0]:=0;
        wz[1]:=min(qz[l,1]-qz[i-1,1],0);
        if qz[l,1]-qz[i-1,1]>0 then u:=1
        else u:=0;
        for j:=2 to m do
        begin
            wz[j]:=qz[l,j]-qz[i-1,j];
            le:=-1;
            ri:=j-u-1;
            while le+1<ri do
            begin
                mid:=(le+ri) div 2;
                if wz[mid]<wz[j] then ri:=mid
                else le:=mid;
            end;
            if wz[j]>wz[ri] then
            u:=max(u,j-ri);
            wz[j]:=min(wz[j],wz[j-1]);
        end;
        ans:=max(ans,u*(l-i+1));
    end;
    writeln(ans);
end.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值