NOI-01:查找最接近的元素 基本二分
01:查找最接近的元素
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
在一个非降序列中,查找与给定值最接近的元素。
- 输入
- 第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。
第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。
第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。
接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间。 - 输出
- m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。
- 样例输入
-
3 2 5 8 2 10 5
- 样例输出
-
8 5
最基本的二分,找点感觉。
但是有小坑。。
二分边界问题,我这种二分的写法,while到最后找到的是两个最接近的值,二选一。
但是当n=1的时候,最后的两个值其实是同一个,a[l+1]是不存在的。。。
特判n=1直接输出即可。
还是就是数组长度不要和寻值个数看错。。数组是开到10W的,不然OJ返回的结果是TLE。。。
#include <iostream> #include <cstdio> #include <cmath> const int maxn = 100000+10; int a[maxn],n; using namespace std; int search(int x) { int l = 1; int r = n; int ans = -1; int mid = (1+n)/2; while(l < r-1) { if(x < a[mid]) { r = mid; } else { l = mid; } mid = (l+r)/2; } if(abs(a[l]-x)<=abs(a[l+1]-x)&&l<n) ans = a[l]; else { ans = a[l+1]; } // if(x-a[l]>a[l+1]-x&&l<n) // l++; return ans; } int main() { // freopen("in.txt","r",stdin); scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); } int T; scanf("%d",&T); while(T--) { int t; scanf("%d",&t); if(n==1) { printf("%d\n",a[1]); } else { printf("%d\n",search(t)); } } return 0; }