二分练习

来源:互联网 发布:网络控制室设备 编辑:程序博客网 时间:2024/05/19 11:45

题目描述

给你一个序列,然后给你m个元素,让你从序列中找出与每个元素最接近的数字输出来,如果有两个就输出两个。
 

输入

 多组输入,第一行给你两个数n(0 < n < 10000000),m(0 < m < n),接下来是数列的n个数,然后再输入m个元素,让你找出最接近每个元素的值。如果有两个,按从小到大输出。
 

输出

 这m个数分别输出最接近每个元素的值,组与组之间输出一个空行。

示例输入

8 41 2 3 4 5 6 8 114927

示例输出

4826 8

提示:典型的二分法,不过不是查找确切的数,而是相近的,由题意可知结果要么是两个数要么是一个数,先调用一个sort函数,将给的数组从小到大排序(这里是为了有两个结果的情况的时候好吧他们找出);

参考代码:
#include<stdio.h>#include<math.h>#include<algorithm>using namespace std;int a[10000007];int main(){    int n,left,right,i,j,mid,m,k,t;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(i=0;i<n;i++)        scanf("%d",&a[i]);        sort(a,a+n);//注意要放在循环外边,不然会超时,开始我就是这样错的,还是让学长改的。        for(j=0;j<m;j++)        {            scanf("%d",&k);            left=0,right=n-1,t=0;            if(k>a[n-1])//判断当测试数据大于最大值的情况,开始因为这个错了好几次            printf("%d\n",a[n-1]);            else if(k<a[0])//判断测试数据小于最小值的情况            printf("%d\n",a[0]);            else        {            while(left<=right)            {                mid=(left+right)/2;                if(k==a[mid])                t=1;                if(k<a[mid])                right=mid-1;                else                left=mid+1;            }//如果测试数据不在数组里,那么最后的区间也是自接近测试数据的            if(t)//数据里有等于测试数据的直接输出            printf("%d\n",k);            else            {                if(a[left]-k==k-a[right])                printf("%d %d\n",a[right],a[left]);//最后区间两边和测试数据一样接近,都打印出来                else if(a[left]-k<k-a[right])//否则打印更接近的                printf("%d\n",a[left]);                else                printf("%d\n",a[right]);            }        }    }        printf("\n");    }    return 0;}


0 0