奶牛浴场

链接:https://www.luogu.org/problemnew/show/P1578

题解也贴上(根本没想到.jpg):https://www.luogu.org/problemnew/solution/P1578

通过枚举某一个点的横坐标作为最大矩形的左边界,然后向右扩展,扩展同时维护上下边界,就行了。不过注意也有可能边界是在最大矩形上,那么如果左右边界都在做大矩形就从小到大枚举纵坐标即可,而如果有一个在,就在做枚举点的左边界的时候枚举完判一下最大矩形右边界对此时答案,然后再暴枚右边界,做类似操作(不差这点常数)。

#include<bits/stdc++.h>
using namespace std;
struct pt{
    int x,y;
}node[5010];
int n,p,q;
bool cmpx(pt x,pt y)
{return x.x<y.x;}
bool cmpy(pt x,pt y)
{return x.y<y.y;}
int main()
{
    int ans=0,nw,l,r,dw,up;
    scanf("%d%d%d",&n,&p,&q);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&node[i].x,&node[i].y);
    sort(node+1,node+n+1,cmpy);
    nw=0;
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,(node[i].y-nw)*p);
        nw=node[i].y;
    }
    ans=max(ans,(q-nw)*p);
    sort(node+1,node+n+1,cmpx);
    for(int i=1;i<=n;i++)
    {
        l=node[i].x;
        dw=0,up=q;
        for(int j=i+1;j<=n;j++)
        {
            r=node[j].x;
            ans=max(ans,(r-l)*(up-dw));
            if(i!=0)
            {
                if(node[j].y>=node[i].y)up=min(up,node[j].y);
                if(node[j].y<=node[i].y)dw=max(dw,node[j].y);
            }
        }
        ans=max(ans,(p-l)*(up-dw));
    }
    for(int i=n;i>=1;i--)
    {
        r=node[i].x;
        dw=0,up=q;
        for(int j=i-1;j>=1;j--)
        {
            l=node[j].x;
            ans=max(ans,(r-l)*(up-dw));
            if(i!=0)
            {
                if(node[j].y>=node[i].y)up=min(up,node[j].y);
                if(node[j].y<=node[i].y)dw=max(dw,node[j].y);
            }  
        }
        ans=max(ans,r*(up-dw));
    }
    cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/caoyang1123/article/details/81635338