zoukankan      html  css  js  c++  java
  • Long Jumps(二分查找lower_bound()函数的运用)

    Valery is a PE teacher at a school in Berland. Soon the students are going to take a test in long jumps, and Valery has lost his favorite ruler!

    However, there is no reason for disappointment, as Valery has found another ruler, its length is l centimeters. The ruler already has nmarks, with which he can make measurements. We assume that the marks are numbered from 1 to n in the order they appear from the beginning of the ruler to its end. The first point coincides with the beginning of the ruler and represents the origin. The last mark coincides with the end of the ruler, at distance l from the origin. This ruler can be repesented by an increasing sequence a1, a2, ..., an, where ai denotes the distance of the i-th mark from the origin (a1 = 0, an = l).

    Valery believes that with a ruler he can measure the distance of d centimeters, if there is a pair of integers i and j (1 ≤ i ≤ j ≤ n), such that the distance between the i-th and the j-th mark is exactly equal to d (in other words, aj - ai = d).

    Under the rules, the girls should be able to jump at least x centimeters, and the boys should be able to jump at least y (x < y) centimeters. To test the children's abilities, Valery needs a ruler to measure each of the distances x and y.

    Your task is to determine what is the minimum number of additional marks you need to add on the ruler so that they can be used to measure the distances x and y. Valery can add the marks at any integer non-negative distance from the origin not exceeding the length of the ruler.

    Input

    The first line contains four positive space-separated integers nlxy (2 ≤ n ≤ 105, 2 ≤ l ≤ 109, 1 ≤ x < y ≤ l) — the number of marks, the length of the ruler and the jump norms for girls and boys, correspondingly.

    The second line contains a sequence of n integers a1, a2, ..., an (0 = a1 < a2 < ... < an = l), where ai shows the distance from the i-th mark to the origin.

    Output

    In the first line print a single non-negative integer v — the minimum number of marks that you need to add on the ruler.

    In the second line print v space-separated integers p1, p2, ..., pv (0 ≤ pi ≤ l). Number pi means that the i-th mark should be at the distance of pi centimeters from the origin. Print the marks in any order. If there are multiple solutions, print any of them.

    Sample test(s)
    input
    2 300 185 230
    0 300
    output
    2
    185 230
    题目意思就是说:

    体育课要考试,一老师拿了一把长度为l的尺子,尺子上标有一些刻度,他要求女生能跳x,男生能跳y(y>x).但是这些刻度不一定能满足测量的要求,告诉你这些刻度,让你判断一下最多需要添加几个点。理解题意很重要,有几点需要注意一下。

    1.一共只需要两个刻度,所以需要的点数只有0,1,2三种可能。

    2.所需要的刻度也可以由ai-aj得到。

    3.多组解符合情况输出任何一组都可以。

    个人心得:made做了一早上set,啥的全用了,该考虑的跨界问题也解决了,就是二重循环把时间卡死了,很无奈,后面看了大神们二分查找才知道,看来得找个机会去看看这个函数的原理啥的。

    题解:

    题目看起来是很简单的,但是却又感觉无从下手。先来分析一下所有情况:

    1.两个距离都能找到,存在某几个点之间距离差恰好等于x,y,添加0个点;

    2.只能找到一个距离x或y,添加1个点;

    3.一个都找不到,但是两个点能共用一个点,只需添加一个公用点。共用一个点的话有两种情况,一种是公用点在三点中间,则能在原刻度上找到两个点使两点间距离满足x+y,另一种情况是公用点在两边,则能在原刻度上找到两个点间距离满足y-x,这种情况在左右添加公共点都可以,但是一定注意不要越过边界。此时添加1个点;

    4.其他,添加2个点;

    情况分析好了之后就很简单了,从前向后遍历,找四个距离,根据查找结果输出答案就好了。因为只差照一次就可以,所以时间上也快了很多。但是有一点需要注意,x,y,x+y都没问题,只要能找到一定能符合情况,但y-x就需要另外判断一下,只满足差值但是往两边添加点时却有可能越界。一定要在查找的时候去判断,比如有两组点满足差值为y-x,如果你在查找到第一组时就跳出,可能第一组是两边都会越界的,此时第二组右边虽然一定越界但左边却可能会满足,所以一定要放在查找的时候去判断。因为这个点wa了无数次,一定要注意。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<set>
     6 #include<map>
     7 #include<vector>
     8 #include<stack>
     9 #include<queue>
    10 #include<algorithm>
    11 #include<iostream>
    12 #include<cstdio>
    13 #include<algorithm>
    14 using namespace std;
    15 int n,l,x,y;
    16 int ch[100005];
    17 int findr(int ans);
    18 void solve()
    19 {
    20     int r1=findr(x),r2=findr(y),r3=findr(x+y),r4=findr(y-x);
    21     if(r1!=-1&&r2!=-1) cout<<"0"<<endl;
    22     else if(r1!=-1)  cout<<"1"<<endl<<y<<endl;
    23     else if(r2!=-1)  cout<<"1"<<endl<<x<<endl;
    24     else
    25     {
    26         if(r4!=-1) cout<<"1"<<endl<<r4<<endl;
    27     else if(r3!=-1) cout<<"1"<<endl<<r3<<endl;
    28     else if(r3==-1&&r4==-1)
    29         cout<<"2"<<endl<<x<<" "<<y<<endl;
    30         }
    31 }
    32 int findr(int ans)
    33 {
    34     int t;
    35     for(int i=0;i<n;i++)
    36       {
    37 
    38           t=lower_bound(ch,ch+n,ch[i]+ans)-ch;
    39           if(t==n)
    40             break;
    41             else
    42             {
    43                 if(ch[t]==ch[i]+ans)
    44                 {
    45                     if(ans==y-x)
    46                     {
    47                         if(ch[t]-y<0&&ch[t]+x>l) continue;
    48                         else if(ch[t]-y>=0) return ch[t]-y;
    49                         else return ch[t]+x;
    50                     }
    51                     else if(ans==x+y)  return ch[t]-y;
    52                     else
    53                         return 1;
    54 }
    55      }
    56     }
    57     return -1;
    58     }
    59 int main()
    60 {
    61 
    62 
    63    cin>>n>>l>>x>>y;
    64    for(int i=0;i<n;i++)
    65    cin>>ch[i];
    66    solve();
    67     return 0;
    68 }
  • 相关阅读:
    Android 手势&触摸事件
    vim常用命令总结
    关于背景中的雪花
    博客园美化——看板娘
    组合数
    扩展欧几里得和求逆元
    dfs序
    RMQ问题
    NOIP2017 列队
    线段树详解
  • 原文地址:https://www.cnblogs.com/blvt/p/7206521.html
Copyright © 2011-2022 走看看