类型:二分+单调队列
传送门:>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; }