[USACO12MAR] 花盆Flowerpot

类型:二分+单调队列

传送门:>Here<

题意:给出$N$个点的坐标,要求根据$x$轴选定一段区间$[L,R]$,使得其中的点的最大与最小的$y$值之差$\geq D$。求$Min\{R-L\}$

解题思路

一道单调队列的好题

思想依然是转化。我们熟知的单调队列的作用也就是滑动窗口——定长区间滚动最大最小值

但是现在区间长度不固定。容易发现,答案满足单调性的,于是可以二分答案。那么问题就转化为定长区间了。然后维护两个单调队列分别做最大与最小值即可

Code

/*By DennyQi 2018.8.18*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = 100010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x<<3) + (x<<1) + c - '0', c = getchar();return x * w;
}
struct Coordinate{
    int x, y;
}a[MAXN];
int N,D,L,R,Mid,Ans,h1,h2,t1,t2;
int qmax[MAXN],qmin[MAXN];
inline bool cmp(const Coordinate& a, const Coordinate& b){
    return a.x < b.x;
}
inline bool judge(int len){
    h1 = h2 = 1, t1 = t2 = 0;
    qmax[0] = qmin[0] = 0;
    for(int i = 1; i <= N; ++i){
        while(h1 <= t1 && a[i].y > a[qmax[t1]].y){
            --t1;
        }
        qmax[++t1] = i;
        while(h2 <= t2 && a[i].y < a[qmin[t2]].y){
            --t2;
        }
        qmin[++t2] = i;
        while(h1 <= t1 && a[i].x - a[qmax[h1]].x > len){
            ++h1;
        }
        while(h2 <= t2 && a[i].x - a[qmin[h2]].x > len){
            ++h2;
        }
        if(a[qmax[h1]].y - a[qmin[h2]].y >= D) return 1;
    }
    return 0;
}
int main(){
    N = r, D = r;
    for(int i = 1; i <= N; ++i){
        a[i].x = r, a[i].y = r;
    }
    sort(a+1, a+N+1, cmp);
    Ans = -1;
    L = 1, R = 1e6+1;
    while(L <= R){
        Mid = (L + R) / 2;
        if(judge(Mid)){
            R = Mid - 1;
            Ans = Mid;
        }
        else{
            L = Mid + 1;
        }
    }
    printf("%d", Ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/qixingzhi/p/9499657.html