题目描述
C市有n名犯罪嫌疑人被叫到公安局问话,有m名目击证人描述了罪犯的身高,经公安局核实,目击证人提供的身高与罪犯实际身高略有误差(目击证人提供的身高是最接近实际身高,且实际身高≤目击者提供身高)。现公安局将所有n名犯罪嫌疑人按身高从低到高站成一排(n个人身高各不相同),并把目击者提供的m个身高都给你,请你快速帮公安局找到罪犯。
输入格式
输入共m+2行 第1行:n,m(m<n≤100000) 第2行:n个嫌疑人的身高(小数点后两位),用空格隔开 后m行:每行1个数,代表目击者提供的1个身高(小数点后两位) 此题可输入1个参考身高输出1名罪犯信息
输出格式
m行,每行两个数,真实罪犯的排序编号和他的身高(用空格隔开) 若提供的身高找不到罪犯,该行输出“NO”
样例
样例输入 1
5 3
1.68 1.70 1.75 1.84 1.86
1.85
1.75
1.68
样例输出 1
4 1.84
3 1.75
1 1.68
样例输入 2
5 3
1.68 1.71 1.74 1.93 1.94
1.72
1.73
1.67
样例输出 2
2 1.71
2 1.71
NO
分析:
输入就不用说了,因为样例可以输入一个身高,输出一个嫌疑人身高,所以我就不统一输出,如果要统一输出的话,先用数组保留数据,最后统一for循环输出。接下来我们来看该如何找出犯人,我们可以用二分来节省找犯人用的时间复杂度,那该如何正确的写出缩短二分范围的代码呢?因为嫌疑人身高为单调递增的,所以我们要找到在小于等于目击者提供身高的所有嫌疑人身高中的最大的那一个,那我们是二分什么呢?应该是嫌疑人身高,所以设变量l和r那是不是二分到比目击者提供身高高的嫌疑人身高就减小r呢?是的,但如果找到了比目击者提供身高矮或一样高的就要缩短l的范围,而不是直接输出嫌疑人的身高。最后要输出l和a[l],但要注意如果目击者提供身高比最矮的哪一位嫌疑人的身高还要矮,就输出NO。还有,因为身高都是两位小数,有精度问题,所以把身高变成long long型。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,a[100005];
double v;
int main(){
scanf("%d %d",&n,&m);
for(long long i=1;i<=n;i++){
scanf("%lf",&v);
a[i]=v*1000;//因为是两位小数,有精度问题,把它变成longlong型
}
for(long long i=1;i<=m;i++){
scanf("%lf",&v);
long long x=v*1000;//x为变成longlong型的目击者提供身高
long long l=0,r=n+1;//要设0和n+1,不然有极端情况
while(l<r-1){
long long mid=(l+r)/2;
if(a[mid]<=x){
l=mid;
}
else{
r=mid;
}
}//二分嫌疑人身高
if(x<a[1]){
cout<<"NO"<<endl;//输出NO
}
else{
printf("%lld %.2lf \n",l,a[l]/1000.0);//把a[l]变成小数
}
}
return 0;
}
求赞!!!!!!!!!!!!!!!!!!!