单调队列 A

题面去内网找

很明显正解要二分答案,如何高效率地check呢
1.搞一发线段树。
2.单调队列。
题挺水的,但是该复习一下单调队列了。

#include <cstdio>
#define N 100005
int read()
{
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    while(x>='0'&&x<='9'){sum=(sum<<3)+(sum<<1)+x-'0';x=getchar();}
    return sum*f;
}
int x,y,z,ans,y1_[N],y2_[N],z1[N],z2[N];
int h[5],t[5],q[5][N];
bool check(int mid)
{
    for(int i=1;i<=4;i++)h[i]=1,t[i]=0;
    for(int i=1;i<=x;i++)
    {
        while(h[1]<=t[1]&&y1_[q[1][t[1]]]<=y1_[i])t[1]--;q[1][++t[1]]=i;
        while(h[2]<=t[2]&&y2_[q[2][t[2]]]>=y2_[i])t[2]--;q[2][++t[2]]=i;
        while(h[3]<=t[3]&&z1[q[3][t[3]]]<=z1[i])t[3]--;q[3][++t[3]]=i;
        while(h[4]<=t[4]&&z2[q[4][t[4]]]>=z2[i])t[4]--;q[4][++t[4]]=i;
        while(h[1]<=t[1]&&q[1][h[1]]<=i-mid)h[1]++;
        while(h[2]<=t[2]&&q[2][h[2]]<=i-mid)h[2]++;
        while(h[3]<=t[3]&&q[3][h[3]]<=i-mid)h[3]++;
        while(h[4]<=t[4]&&q[4][h[4]]<=i-mid)h[4]++;
        if(i>=mid&&y2_[q[2][h[2]]]-y1_[q[1][h[1]]]+1>=mid&&z2[q[4][h[4]]]-z1[q[3][h[3]]]+1>=mid)return 1;
    }
    return 0;
}
int main()
{
    x=read();y=read();z=read();
    for(int i=1;i<=x;i++)
       y1_[i]=read(),z1[i]=read(),y2_[i]=read(),z2[i]=read();
    int l=1,r=x,mid;
    while(l<=r)
    {
        mid=l+r>>1;
        if(check(mid))l=mid+1;
        else r=mid-1;
    }
    printf("%d\n",l-1);
}
posted @ 2017-10-20 18:38  Hzoi_QTY  阅读(202)  评论(3编辑  收藏  举报