题目描述
游戏积分的排行榜出来了,小z想看看得某个积分的人是谁。但是由于人数很多,他自己找很浪费时间,所以他想请你帮忙写一个程序,能快速的帮他找到他想要找的人
输入
多组测试数据,第一行有一个数T,表示有T组测试数据(T<=50)
第二行有两个数n和m(1<=n,m<=10000),n表示有n个人,m表示有m次查询
接下来n行,输入每个人的名字(长度小于10)和积分num(0<=num<=10^8),
接下来m行,每个数表示要查询的积分(每次查询一定有结果)
输出
输出对应积分的人的名字(如果有多个人的积分相同,则输出最前面的那个)
样例输入
1 5 3 zhangsan 2 qianxiao 5 liuqiang 2 wangwu 1 lisi 3 2 1 3
样例输出
zhangsan wangwu lisi
分析:既然有1e4个人和1e4次的访问,那么肯定不能挨个查找了,这样子很容易就超时挂掉了。我们一开始就会想到利用二分查找。是的,先对本题的数据进行结构体排序,然后进行二分查找即可,但题目要求“如果有多个人的积分相同,则输出最前面的那个”,如果利用二分查找,我们不一定就能访问到相同情况下的第一个。我们可能查找到的是相同的第二个或者最后一个,这样子是不成立的。
笔者一开始想要用到STL中的lower_bound()函数,这样就能返回查找到相同元素中的第一个的地址,但由于是结构体形式的查找则变复杂了。后连笔者发现可以自定义一个二分函数,在原函数基础上进行一些修改即可,如果二分查找到了对应的值,我们可以先判断一下前一个值与对应的值是否相等,如果相等,则将范围缩小再进行一次二分。最后一定可以找到相同中的第一个对应的值输出即可。
另外就是大数据查找时千万不要用cin和cout输出,这两种输入输出方式面对大数据远比scanf和printf慢很多,笔者前几次因为这样做而超时挂掉。
#include<algorithm>
#include<stdio.h>
using namespace std;
struct Buf
{
int sco;char name[11];//定义结构体用于存储数据
}buf[10005];
bool cmp(Buf a,Buf b)
{
return a.sco<b.sco;//定义升序的结构体排序
}
int Binary_search(int l,int r,int k)//定义二分查找函数
{
int mid;
while(l<r)
{
mid=(l+r)/2;
if(buf[mid].sco>k)
r=mid;
else if(buf[mid].sco<k)
l=mid+1;
else
{
if(buf[mid].sco==buf[mid-1].sco)//如果查找到对应的值,看前一个值是否与其相等
r=mid //相等的话,再进行二分查找缩小区间范围,直到找到符合条件的值
else
return mid;//如果前一个值不与其相等,则一定是相等数中的第一个,直接返回即可
}
}
}
int main()
{
int t,m,n,key,c;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%s%d",buf[i].name,&buf[i].sco);//向结构体中输入数据
stable_sort(buf,buf+n,cmp);//进行稳定快排(用sort会WA掉)
for(int i=0;i<m;i++)
{
scanf("%d",&key);
c=Binary_search(0,n,key);//输入数据进行二分查找
printf("%s\n",buf[c].name);//输出对应的名字
}
}
}