题意:
体育课要考试,一老师拿了一把长度为l的尺子,尺子上标有一些刻度,他要求女生能跳x,男生能跳y(y>x).但是这些刻度不一定能满足测量的要求,告诉你这些刻度,让你判断一下最多需要添加几个点。理解题意很重要,有几点需要注意一下。
1.一共只需要两个刻度,所以需要的点数只有0,1,2三种可能。
2.所需要的刻度也可以由ai-aj得到。
3.多组解符合情况输出任何一组都可以。
题解:
题目看起来是很简单的,但是却又感觉无从下手。先来分析一下所有情况:
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了无数次,一定要注意。
代码实现:
<span style="font-size:14px;">#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <algorithm>
#define INF 1000000009
#define MAX 100005
using namespace std;
int a[MAX];
bool solve();//主实现函数
int finds(int);//查找函数
int n,length,x,y;
int main()
{
scanf("%d%d%d%d",&n,&length,&x,&y);
memset(a,0,sizeof(a));
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
//主实现函数
solve();
return 0;
}
bool solve()
{
//定义四个变量储存返回结果,找不到返回-1,找得到返回右侧的点
int r1,r2,r3,r4;
//查找四个距离
r1=finds(x);
r2=finds(y);
r3=finds(x+y);
r4=finds(y-x);
//x,y都找到
if(r1!=-1&&r2!=-1)
{
printf("0\n");
}
else
{
//仅x找到
if(r1!=-1)
printf("%d\n%d\n",1,y);
//仅y找到
else if(r2!=-1)
printf("%d\n%d\n",1,x);
//x+y找到
else if(r3!=-1)
printf("%d\n%d\n",1,r3-y);
//y-x找到
else if(r4!=-1)
{
if(r4-y>0)
printf("%d\n%d\n",1,r4-y);
else if(r4+x<length)
printf("%d\n%d\n",1,r4+x);
}
//都找不到
else
printf("%d\n%d %d\n",2,x,y);
}
return true;
}
int finds(int pos)
{
int tmp;
for(int i=0;i<n;i++)
{
//二分查找满足距离的点
tmp=lower_bound(a,a+n,a[i]+pos)-a;
//找不到
if(tmp==n)
break;
else
{
//满足距离的点存在
if(a[tmp]==a[i]+pos)
{
//距离为y-x时要格外注意
if(pos==y-x)
{
if(a[tmp]-y<0&&a[tmp]+x>length)
continue;
else
return a[tmp];
}
//返回右测点的位置
else
return a[tmp];
}
}
}
//不满足返回-1
return -1;
}</span>