zoukankan      html  css  js  c++  java
  • [单调队列][二分] 洛谷 P2698 花盆

    题目描述

    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。

    输入输出格式

    输入格式:

    第一行2个整数 N 和 D。

    第2.. N+1行每行2个整数,表示水滴的坐标(x,y)。

    输出格式:

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

    输入输出样例

    输入样例#1:
    4 5
    6 3
    2 4
    4 10
    12 15
    输出样例#1:
    2

    说明

    【样例解释】

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

    【数据范围】

    40%的数据:1 ≤ N ≤ 1000,1 ≤ D ≤ 2000;

    100%的数据:1 ≤ N ≤ 100000,1 ≤ D ≤ 1000000,0≤x,y≤10^6。

    题解

    • 考虑一下二分出一个花盆的宽度,然后用单调对列判断是否满足时间差大于等于D

    代码

     1 #include <cstdio> 
     2 #include <iostream>
     3 #include <cstring>
     4 #define N 1000010
     5 using namespace std;
     6 int n,d,mx,maxv[N],minv[N],a[N],b[N];
     7 bool check(int x)
     8 {
     9     int headx=0,heady=0,tailx=0,taily=0;
    10     for (int i=0;i<=mx;i++)
    11         if (maxv[i]+1)
    12         {
    13             while (headx<tailx&&i-a[headx]>x) headx++;
    14             while (heady<taily&&i-b[heady]>x) heady++;
    15             while (headx<tailx&&maxv[i]>=maxv[a[tailx-1]]) tailx--;
    16             while (heady<taily&&minv[i]<=minv[b[taily-1]]) taily--;
    17             a[tailx++]=i,b[taily++]=i;
    18             if (maxv[a[headx]]-minv[b[heady]]>=d) return true;
    19         }
    20     return false;
    21 }
    22 int main()
    23 {
    24     memset(maxv,-1,sizeof(maxv)),memset(minv,-1,sizeof(minv));
    25     scanf("%d%d",&n,&d);
    26     for (int i=1,x,y;i<=n;i++)
    27     {
    28         scanf("%d%d",&x,&y),mx=max(mx,y);
    29         if (maxv[x]==-1) maxv[x]=minv[x]=y;
    30         maxv[x]=max(maxv[x],y),minv[x]=min(minv[x],y);
    31     }
    32     int l=1,r=mx+1;
    33     while (l<r)
    34     {
    35         int mid=(l+r)>>1;
    36         if (check(mid)) r=mid; else l=mid+1;
    37     } 
    38     printf("%d",r==mx+1?-1:r);
    39 }
  • 相关阅读:
    Hdu 5396 Expression (区间Dp)
    Lightoj 1174
    codeforces 570 D. Tree Requests (dfs)
    codeforces 570 E. Pig and Palindromes (DP)
    Hdu 5385 The path
    Hdu 5384 Danganronpa (AC自动机模板)
    Hdu 5372 Segment Game (树状数组)
    Hdu 5379 Mahjong tree (dfs + 组合数)
    Hdu 5371 Hotaru's problem (manacher+枚举)
    Face The Right Way---hdu3276(开关问题)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9807362.html
Copyright © 2011-2022 走看看