7-45 航空公司VIP客户查询 (25 分)
不少航空公司都会提供优惠的会员服务,当某顾客飞行里程累积达到一定数量后,可以使用里程积分直接兑换奖励机票或奖励升舱等服务。现给定某航空公司全体会员的飞行记录,要求实现根据身份证号码快速查询会员里程积分的功能。
输入格式:
输入首先给出两个正整数N(≤10
5
)和K(≤500)。其中K是最低里程,即为照顾乘坐短程航班的会员,航空公司还会将航程低于K公里的航班也按K公里累积。随后N行,每行给出一条飞行记录。飞行记录的输入格式为:18位身份证号码(空格)飞行里程。其中身份证号码由17位数字加最后一位校验码组成,校验码的取值范围为0~9和x共11个符号;飞行里程单位为公里,是(0, 15 000]区间内的整数。然后给出一个正整数M(≤10
5
),随后给出M行查询人的身份证号码。
输出格式:
对每个查询人,给出其当前的里程累积值。如果该人不是会员,则输出No Info。每个查询结果占一行。
输入样例:
4 500
330106199010080419 499
110108198403100012 15000
120104195510156021 800
330106199010080419 1
4
120104195510156021
110108198403100012
330106199010080419
33010619901008041x
输出样例:
800
15000
1000
No Info
思路:一开始写了个关于string类的映射,很快就写出来了,看了看限制时间,觉得会超时,一跑,果然超时了,后来觉得可能是cin输入太费时间,不用c++中的map容器,自己写了个Map函数,用scanf接受字符串,然后重写,再次超时,之后感觉没什么思路,只好跑去看别人的博客,由于不怎么喜欢搬别人的代码,随便看了看别人用的什么方法就跑去自己想了,看到别人用的是long long 类型的映射,觉得奇怪,觉得long long类型不是32位的吗,结果一去百度,发现自己记错了,然后改用long long 类型的映射
由于题目中的身份证号比较特殊,光靠long long类型无法完成题目中的映射,所以身份证号还是要靠字符串来接受,之后再转化为long long类型的即可
第二个测试点的坑是:可能两个身份证号的前十七位全部相等,只有最后一位不同
代码中还用到了一个平时不怎么用的函数:sscanf
在想字符串转化为数字的时候突然想起了刘汝佳的那本紫书里有段代码用到了这个函数作为其他数据的输入,感觉在这题会很方便,里面的输入控制字符串可以利用正则表达式完成各种灵活的转换,写完之后果然AC 了
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
int main()
{
map<long long,int> p;
int N, M, K;
char ID[20];
cin >> N >> K;
for(int i=0;i < N;i++){
int range;
long long temp;
scanf("%s %d",ID,&range);
if(ID[17] != 'x'){
sscanf(ID,"%18lld",&temp);
}
else{
sscanf(ID,"%17lld",&temp);
temp = -temp;
}
if(range < K){
range = K;
}
p[temp] += range;
}
cin >> M;
for(int i=0;i < M;i++){
long long temp;
scanf("%s",ID);
if(ID[17] != 'x'){
sscanf(ID,"%18lld",&temp);
}
else{
sscanf(ID,"%17lld",&temp);
temp = -temp;
}
if(p[temp] != 0){
printf("%d\n",p[temp]);
}
else{
printf("No Info\n");
}
}
return 0;
}