Flowerpot S

Luogu P2698

Problem Statement

Farmer John has been having trouble making his plants grow, and needs your help to water them properly. You are given the locations of N raindrops (1 <= N <= 100,000) in the 2D plane, where y represents vertical height of the drop, and x represents its location over a 1D number line:

Each drop falls downward (towards the x axis) at a rate of 1 unit per second. You would like to place Farmer John’s flowerpot of width W somewhere along the x axis so that the difference in time between the first raindrop to hit the flowerpot and the last raindrop to hit the flowerpot is at least some amount D (so that the flowers in the pot receive plenty of water). A drop of water that lands just on the edge of the flowerpot counts as hitting the flowerpot.

Given the value of D and the locations of the N raindrops, please compute the minimum possible value of W.

老板需要你帮忙浇花。给出 $N$ 滴水的坐标,$y$ 表示水滴的高度,$x$ 表示它下落到 $x$ 轴的位置。

每滴水以每秒 $1$ 个单位长度的速度下落。你需要把花盆放在 $x$ 轴上的某个位置,使得从被花盆接着的第 $1$ 滴水开始,到被花盆接着的最后 $1$ 滴水结束,之间的时间差至少为 $D$。

我们认为,只要水滴落到 $x$ 轴上,与花盆的边沿对齐,就认为被接住。给出 $N$ 滴水的坐标和 $D$ 的大小,请算出最小的花盆的宽度 $W$。

Input

第一行 $2$ 个整数 $N$ 和 $D$。

接下来 $N$ 行每行 $2$ 个整数,表示水滴的坐标 $(x,y)$。

Output

仅一行 $1$ 个整数,表示最小的花盆的宽度。如果无法构造出足够宽的花盆,使得在 $D$ 单位的时间接住满足要求的水滴,则输出 $-1$。

Sample Input

1
2
3
4
5
4 5
6 3
2 4
4 10
12 15

Sample Output

1
2

Explanation of example

有 $4$ 滴水,$(6,3)$ ,$(2,4)$ ,$(4,10)$ ,$(12,15)$ 。水滴必须用至少 $5$ 秒时间落入花盆。花盆的宽度为 $2$ 是必须且足够的。把花盆放在 $x=4\dots6$ 的位置,它可以接到 $1$ 和 $3$ 水滴, 之间的时间差为 $10-3=7$ 满足条件。

Constraints

$40%$ 的数据:$1 \le N \le 1000$ ,$1 \le D \le 2000$ 。

$100%$ 的数据:$1 \le N \le 10 ^ 5$ ,$1 \le D \le 10 ^ 6$ ,$0\le x,y\le10^6$ 。

Solving

题意大致为我们维护一个宽度为 L 的窗口(花盆) 使得花盆中存在的水滴高度的最大值减去最小值大于等于D,我们要找到满足条件的最小宽度L。

对于求解一滑动窗口内的最值,我们可以同时维护两个单调队列,分别获取窗口内的最大最小值。

所以题目的大致解决思路为:

将读取的水滴数据按照X坐标进行离散化处理并进行升序排序,在坐标轴从左至右不断扩张窗口至能满足窗口内最大值-最小值>=D随后开始尝试收缩窗口左边界至不再满足条件,随后按照正常滑动窗口的思路进行滑动,途中不断更新答案宽度L的最小值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define INF 0x3f3f3f3f
#define NINF -0x3f3f3f3f
#define Single
using namespace std;
using ll = long long;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int N = 1e5+10;
const int M = 0; 
int n,D;
struct node
{
    int x;// 水滴落点
    int sec;// 水滴下落时间
}drip[N];

deque<int> qmax;
deque<int> qmin;

bool cmp(node a,node b) { return a.x < b.x; }

void solve()
{   
    cin >> n >> D;
    for(int i=0;i<n;i++)
    {
        cin >> drip[i].x >> drip[i].sec;
    }
    sort(drip,drip+n,cmp);
    int ans = LLONG_MAX;
    
    int tail = drip[0].x;//尾指针指向离散化后的窗口左边界
    int index = 0;//指针指向未离散化时的窗口左边界
    int head;//头指针指向离散化后的窗口右边界
    //指针i为未离散化的窗口右边界
    for(int i=0;i<n;i++)
    {   
        head = drip[i].x;
        //求最大值的单调递减队列
        while(!qmax.empty()&&drip[i].sec >= qmax.back()) qmax.pop_back();
        qmax.push_back(drip[i].sec);
        //求最小值的单调递增队列
        while(!qmin.empty()&&drip[i].sec <= qmin.back()) qmin.pop_back();
        qmin.push_back(drip[i].sec);
        //满足条件时收缩左边界
        while(qmax.front()-qmin.front() >= D)
        {
            ans = min(ans,head-tail);
            if(drip[index].sec==qmax.front()) qmax.pop_front();
            if(drip[index].sec==qmin.front()) qmin.pop_front();
            index++;//未离散化的左边界
            tail = drip[index].x;//离散化后的左边界      
        }
    }
    if(ans==LLONG_MAX)
    {
        cout << -1;
    }
    else
    cout << ans;
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    int T;
#ifdef Single
    T = 1;
#else
    cin >> T;
#endif
    while(T--)
    {
        solve();
    }
    return 0;
}
Licensed under CC BY-NC-SA 4.0
Member of the Qilu University Of Technology ACM-ICPC Association
Built with Hugo
Theme Stack designed by Jimmy