【单调队列】[CQBZOJ2436]Zj 之 XX 洗浴

来源:互联网 发布:众途软件价格 编辑:程序博客网 时间:2024/06/11 20:07

题目描述
众所周知,这个就不扩展了……
自从这次被抓以后,zj同学很不服气。回家后,zj 就开始了他的计划!(你不让我
洗浴,我就在家洗个痛快!)zj 打算在自家的院子里修一个洗浴池,当然他希望洗
浴池越大越好。但是院子里有 zj喜欢的一些植物,他不想毁掉任一颗植物,所以洗浴池不能将植物的位置占掉。zj的院子和洗浴池都是矩形的,浴池要完全处在院
子里,并且浴池的轮廓要与院子的轮廓平行或重合。每个植物可以看做一个点,浴
池不能覆盖任何一个植物点,但是植物点可以在浴池的边上,请问 zj 的浴池最大
能修多大.
输入
输入文件的第一行包含两个整数l和w,分别表示院子的长和宽。文件的第二行包
含一个整数n,表示植物的数量。以下n行每行包含两个整数x和y,表示一个植物
点的坐标。所有植物点都位于院子内,即:0 ≤ x ≤ l,0 ≤ y ≤ w。
输出
输出文件仅一行,包含一个整数s,表示浴池的最大面积。

样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

10 10
4
1 1
9 1
1 9
9 9
样例输出
80
提示
【数据范围】

0 ≤ n ≤ 5000,1 ≤ l ,w ≤ 30000

来源
HZOI

对每一行的点,找出它到该列上方最近的植物点的距离,可以看做矩形的最大宽度,然后向左右延伸,对每一行都求出一个最大的矩形。所有行的最大矩形即为答案。
总的时间复杂度为O(N^N).
本题点的坐标范围太大,需要先进行离散化。
要用单调队列或者堆栈进行优化。

#include<cstdio>#include<algorithm>#include<queue>using namespace std;#define MAXN 5000bool mat[MAXN+10][MAXN+10];void Read(int &x){    char c;    while(c=getchar(),c!=EOF)        if(c>='0'&&c<='9'){            x=c-'0';            while(c=getchar(),c>='0'&&c<='9')                x=x*10+c-'0';            ungetc(c,stdin);            return;        }}int l,w,n,ans,x[MAXN+10],cntx,cnty,y[MAXN+10],h[MAXN+10],s[MAXN+10],front,rear;pair<int,int>a[MAXN+10],q[MAXN+10];void init(){    Read(l),Read(w),Read(n);    int i;    for(i=1;i<=n;i++){        Read(a[i].first),Read(a[i].second);        x[i]=a[i].first;        y[i]=a[i].second;    }    x[n+1]=l;    y[n+1]=w;    sort(x+1,x+n+2);    cntx=unique(x,x+n+2)-x-1;    sort(y+1,y+n+2);    cnty=unique(y,y+n+2)-y-1;    for(i=1;i<=n;i++)        mat[lower_bound(x+1,x+cntx+1,a[i].first)-x][lower_bound(y+1,y+cnty+1,a[i].second)-y]=1;}void solve(){    int i,j;    for(i=1;i<=cntx;i++){        front=1,rear=0;        q[0]=make_pair(0,0);        for(j=1;j<=cnty;j++){            h[j]+=x[i]-x[i-1];            while(front<=rear&&q[rear].first>=h[j])                rear--;            s[j]=h[j]*(y[j]-q[rear].second);            q[++rear]=make_pair(h[j],y[j]);        }        front=1,rear=0;        q[0]=make_pair(0,w);        for(j=cnty-1;j;j--){            while(front<=rear&&q[rear].first>h[j])                rear--;            s[j]+=h[j]*(q[rear].second-y[j]);            q[++rear]=make_pair(h[j],y[j]);            ans=max(ans,s[j]);            if(mat[i][j])                h[j]=0;        }    }    for(j=1;j<=cnty;j++)        ans=max(ans,l*(y[j]-y[j-1]));}int main(){    init();    solve();    printf("%d",ans);}
0 0
原创粉丝点击