传送门
//对于每一个学生的分数, 找和该分数最近的学校即可.
//当然用二分找啊, 然后如果熟练运用了lower_bound 和 upper_bound(下面会详细介绍介绍) , 那么直接上就可以, 否则你就直接手写这两个函数(xx, 博主不是很会手写哎,大概知道一些 )也是可以的. 注意边界条件! 即第0个学校就另成一个极值, 反正就是如果没有符合的, 就选边界.
AC Code : (lower_bound 写法)
/** @Cain*/
const int maxn=1e5+5;
int m,n;
int a[maxn],b[maxn];
void solve()
{
while(~scanf("%d%d",&m,&n)){
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
a[0] = -inf, a[m+1] = inf; //特别注意边界条件.
sort(a,a+2+m);
ll res = 0;
for(int i=1;i<=n;i++){
int tmp = lower_bound(a+1,a+1+m,b[i])-a;
res += min(abs(a[tmp-1] - b[i]),abs(a[tmp] - b[i]));
}
printf("%lld\n",res);
}
}
1:lower_bound【返回第一个大于等于要查找的数的下标位置!】
例 :
//如果是单纯的找我们要找的值的话, 都是减的数组首地址, 不管是什么下标开头, 返回的值, 该怎么用就怎么用.
//但是在离散化里面用的话还是有一点不一样, 因为要看你愿意让下标从什么开头, 总之用的时候根据题意的要求适当的画一画, 然后在写!!!
/** @Cain*/
#include <bits/stdc++.h>
using namespace std;
int n;
int a[10] = {1,2,3,5,6,7,8,9};
int main()
{
while(~scanf("%d",&n)){
int pos = lower_bound(a,a+8,n)-a;
cout << pos << endl;
}
}
手写: (所以上面那么换成手写的也是可以, 我就不写了)
/** @Cain*/
#include <bits/stdc++.h>
using namespace std;
int n;
int a[10] = {0,5,6,7,8,9,513,567,600};
int main()
{
while(~scanf("%d",&n)){
int l =1,r =8,mid;
while(r-l>0){
mid = (r+l) >> 1;
if(a[mid] >= n) r = mid ;
else l = mid + 1 ;
}
printf("%d %d\n",l,a[l]);
}
}
2:upper_bound【返回第一个小于等于要查找的数的下标位置!】 和lower_bound类似, 就不多说了.
只有在要被查找的数组里有重复元素的时候这两个函数有点区别.
//个人觉得, 既然有函数, 那就用函数啊, 写的又快, 又能减少错误, 为什么不用了?