二分练习
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
给你一个序列,然后给你m个元素,让你从序列中找出与每个元素最接近的数字输出来,如果有两个就输出两个。
输入
多组输入,第一行给你两个数n(0 < n < 10000000),m(0 < m < n),接下来是数列的n个数,然后再输入m个元素,让你找出最接近每个元素的值。如果有两个,按从小到大输出。
输出
这m个数分别输出最接近每个元素的值,组与组之间输出一个空行。
示例输入
8 4 1 2 3 4 5 6 8 11 4 9 2 7
示例输出
4 8 2 6 8
提示
来源
lwn
示例程序
一晚上都耗在这道题上了,二分的变形问题,因为涉及的数有多个,传统的不好确定位置,所以得求出它的上下界函数,在这个的基础上展开求。在此多谢赵鹏学长,orz~
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int x[10000010];
int down(int a[],int low,int high, int key)//求下界函数,即小于key的最大值;
{
int res=-1;
while (low<=high)//注意等号
{
int mid=(high+low)/2;
if(a[mid]<=key)
{
low=mid+1;
res=mid;
}
else
high=mid-1;
}
return res;
}
int up(int a[],int low,int high,int key)//求上界函数,即大于key的最小值;
{
int res=-1;
while (low<=high)
{
int mid=(low+high)/2;
if(a[mid]<key)
low=mid+1;
else
{
res=mid;
high=mid-1;
}
}
return res;
}
int main()
{
int n,m,i;
int nmax,nmin,key;
while(~scanf("%d %d",&n,&m))
{
for(i=0;i<n;i++)
scanf("%d",&x[i]);
sort(x,x+n);
while (m--)
{
scanf("%d",&key);
nmax=up(x,0,n-1,key);
nmin=down(x,0,n-1,key);
if(nmin==-1)//这个需要判断一下,因为不一定能求到比它小的数;
{
printf("%d\n",x[nmax]);
}
else if(nmax==-1)//同样,这个不一定能求到比它大的数;
{
printf("%d\n",x[nmin]);
}
else if(x[nmax]==x[nmin])//上下界函数求到一样的值,即key值,直接输出;
printf("%d\n",x[nmin]);
else
{
if(key-x[nmin]==x[nmax]-key)//key值没有,左右两个差值一样,即输出;
printf("%d %d\n",x[nmin],x[nmax]);
else if(key-x[nmin]<x[nmax]-key)
printf("%d\n",x[nmin]);
else
printf("%d\n",x[nmax]);
}
}
printf("\n");//审清题,别忘记这个;
}
return 0;
}