洛谷 P1578 奶牛浴场 题解

题面

1、定义有效子矩形为内部不包含任何障碍点且边界与坐标轴平行的子矩形。如图所示,第一个是有效子矩形(尽管边界上有障碍点),第二个不是有效子矩形(因为内部含有障碍点)。

2、极大有效子矩形:一个有效子矩形,如果不存在包含它且比它大的有效子矩形,就称这个有效子矩形为极大有效子矩形。(为了叙述方便,以下称为极大子矩形)

3、定义最大有效子矩形为所有有效子矩形中最大的一个(或多个)。以下简称为最大子矩形。

综上所述:

在一个有障碍点的矩形中的最大子矩形一定是一个极大子矩形。

算法的思路是通过枚举所有的极大子矩形找出最大子矩形。根据这个思路可以发现,如果算法中有一次枚举的子矩形不是有效子矩形、或者不是极大子矩形,那么可以肯定这个算法做了“无用功”,这也就是需要优化的地方。怎样保证每次枚举的都是极大子矩形呢,我们先从极大子矩形的特征入手。

这种枚举障碍点的算法的时间复杂度是O(S^2)。

#include <bits/stdc++.h>
using namespace std;
struct haha{
    int x;
    int y;
}lala[10010];
int L,R;
int n;
void pre()
{
    lala[++n].x=0,lala[n].y=0;
    lala[++n].x=L,lala[n].y=0;
    lala[++n].x=0,lala[n].y=R;
    lala[++n].x=L,lala[n].y=R;
}
bool cmp(haha x,haha y)
{
    return x.x<y.x;
}
bool cmp2(haha x,haha y)
{
    return x.y<y.y;
}
int main()
{
    cin>>L>>R;
    cin>>n;
    for(register int i=1;i<=n;i++){
        scanf("%d%d",&lala[i].x,&lala[i].y);
    }
    pre();
    sort(lala+1,lala+1+n,cmp);
    int res=0;
    for(register int i=1;i<=n;i++){        
        register int height=R,l=0,v=L-lala[i].x;
        for(register int j=i+1;j<=n;j++){
            if(lala[i].y<=height&&lala[i].y>=l){
                if(v*(height)<=res) break;
                res=max(res,(lala[j].x-lala[i].x)*(height-l));
                if(lala[j].y==lala[i].y) break;
                if(lala[j].y>lala[i].y) height=min(height,lala[j].y);
                else{
                    l=max(l,lala[j].y);
                }
            }
        }
        height=R;
        l=0;
        v=lala[i].x;
        for(int j=i-1;j>=1;j--){
            if(lala[i].y<=height&&lala[i].y>=l){
                if(v*(height)<=res) break;
                res=max(res,(lala[i].x-lala[j].x)*(height-l));
                if(lala[j].y==lala[i].y) break;
                if(lala[j].y>lala[i].y) height=min(height,lala[j].y);
                else{
                    l=max(l,lala[j].y);
                }
            }
        }
    }
    sort(lala+1,lala+1+n,cmp2);
    for(register int i=1;i<=n-1;i++){
        res=max(res,(lala[i+1].y-lala[i].y)*L);
    }
    cout<<res;
}