10.19T4 二分+线段树/ST表维护区间最值

Description

  FJ需要你帮忙浇花。给出N滴水的坐标,y表示水滴的高度,x表示它下落到x轴的位置。
    
  每滴水以每秒1个单位长度的速度下落。你需要把花盆放在x轴上的某个位置,使得从被花盆接着的第1滴水开始,到被花盆接着的最后1滴水结束,之间的时间差至少为D。
  我们认为,只要水滴落到x轴上,与花盆的边沿对齐,就认为被接住。
  给出N滴水的坐标和D的大小,请算出最小的花盆的宽度W。

Input

  第1行: 2个整数 N 和 D. 
  第2..1+N行: 第行2个整数,表示水滴的坐标 (x,y),坐标在 0...1,000,000范围内

Output

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

Sample Input

4 5
6 3
2 4
4 10
12 15

Sample Output

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

Hint

【数据规模】1 ≤ N ≤ 100000,1 ≤ D ≤ 1000000
 
 
 
很显然我们可以二分花盆的大小然后枚举每一个点的右区间进行区间查询就可以了
当然我这种弱鸡只能写线段树了
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define N 1000005
 5 #define lc (p<<1)
 6 #define rc (p<<1|1)
 7 using namespace std;
 8 struct node {
 9     int l,r,min,max;
10 } t[N];
11 struct T {
12     int x,y;
13 }e[N];
14 void pushup(int p) {
15     t[p].max=max(t[lc].max,t[rc].max);
16     t[p].min=min(t[lc].min,t[rc].min);
17 }
18 void build(int p,int l,int r) {
19     t[p].l=l,t[p].r=r;
20     if(l==r) {
21         t[p].max=t[p].min=e[l].y;
22         return ;
23     }
24     int mid=l+r>>1;
25     build(lc,l,mid);
26     build(rc,mid+1,r);
27     pushup(p);
28 }
29 int query_max(int p,int ql,int qr) {
30     if(ql<=t[p].l&&t[p].r<=qr) {
31         return t[p].max;
32     }
33     int ans=0;
34     int mid=t[p].l+t[p].r>>1;
35     if(ql<=mid)ans=max(ans,query_max(lc,ql,qr));
36     if(qr>mid)ans=max(ans,query_max(rc,ql,qr));
37     return ans;
38 }
39 int query_min(int p,int ql,int qr) {
40     if(ql<=t[p].l&&t[p].r<=qr) {
41         return t[p].min;
42     }
43     int ans=0x3f3f3f3f;
44     int mid=t[p].l+t[p].r>>1;
45     if(ql<=mid)ans=min(ans,query_min(lc,ql,qr));
46     if(qr>mid)ans=min(ans,query_min(rc,ql,qr));
47     return ans;
48 }
49 bool cmp(const T&a,const T&b) {
50     return a.x<b.x;
51 }
52 int a[N];
53 int n,D;
54 bool check(int mid) {
55     for(int i=1; i<=n; i++) {
56         if(a[i]+mid>a[n])continue;
57         int r=upper_bound(a+1,a+n+1,a[i]+mid)-a-1;
58         if(query_max(1,i,r)-query_min(1,i,r)>=D)return true;
59     }
60     return false;
61 }
62 int main() {
63     cin>>n>>D;
64     for(int i=1; i<=n; i++) {
65         cin>>e[i].x>>e[i].y;
66     }
67     sort(e+1,e+n+1,cmp);
68     build(1,1,n);
69     for(int i=1; i<=n; i++)a[i]=e[i].x;
70     int l=0,r=e[n].x-e[1].x;
71     int ans=-1;
72     while(l<=r) {
73         int mid=l+r>>1;
74         if(check(mid))r=mid-1,ans=mid;
75         else l=mid+1;
76     }
77     cout<<ans;
78     return 0;
79 }

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9818906.html