<---
大佬们点个赞吧qwq
2019 年浙江大学将要庆祝成立 122 周年。
为了准备校庆,校友会收集了所有校友的身份证号。
现在需要请你编写程序,根据来参加校庆的所有人士的身份证号,统计来了多少校友。
输入格式
输入在第一行给出正整数 N。
随后 N 行,每行给出一位校友的身份证号(18 位由数字和大写字母 X 组成的字符串)。题目保证身份证号不重复。
随后给出前来参加校庆的所有人士的信息:
首先是一个正整数 M。
随后 M 行,每行给出一位人士的身份证号。题目保证身份证号不重复。
输出格式
首先在第一行输出参加校庆的校友的人数。
然后在第二行输出最年长的校友的身份证号 —— 注意身份证第 7−14 位给出的是 yyyymmdd
格式的生日。
如果没有校友来,则在第二行输出最年长的来宾的身份证号。题目保证这样的校友或来宾必是唯一的。
数据范围
1≤N,M≤105
输入样例:
5
372928196906118710
610481197806202213
440684198612150417
13072819571002001X
150702193604190912
6
530125197901260019
150702193604190912
220221196701020034
610481197806202213
440684198612150417
370205198709275042
输出样例:
3
150702193604190912
思路
一看这题数据范围:105!暴力 O(n2) 大概就 1010 了,肯定不行。那该怎么做呢?
我看题解区用unordered_set
的比较少,就来讲一下用unordered_set
的方法吧!
- 分别声明两个
unordered_set
a,b,a 用来记录所有校友的身份证号,b 用来记录参加校庆的所有人士的身份证号 - 读入之后用
unordered_set::count
方法记录参加校庆的校友的人数 - 判断一下:如果没有校友来,就在 b 里找答案,否则就在 a 里面找,然后输出
坑点
这道题的坑点在于题目描述太不清晰了,很容易让人误会,像比如说:
然后在第二行输出最年长的校友的身份证号 —— 注意身份证第 7−14 位给出的是
yyyymmdd
格式的生日。
这里的校友居然指的是参加校庆的校友,我这个阅读能力不行的xxs一脸懵逼
代码
#include <iostream>
#include <unordered_set> // unordered_set的头文件
using namespace std;
int n, m;
unordered_set<string> a, b, t; // a: 所有校友, b: 参加校庆的所有人士, t: 要从里面找答案的集合(为了节省码长)
string id;
int main()
{
ios::sync_with_stdio(0); // 提高输入输出速度
cin.tie(0); // 这个也是
cin >> n;
while (n -- ) // 输入所有校友的身份证号
{
cin >> id;
a.insert(id);
}
cin >> m;
while (m -- ) // 输入参加校庆的所有人士的身份证号
{
cin >> id;
b.insert(id);
}
int cnt = 0; // cnt: 多少校友来了
for (auto e : b) // 遍历b
cnt += a.count(e);
cout << cnt << '\n'; // 输出
if (!cnt) t = b; // 如果没有校友来,就在参加校庆的所有人士里面找答案
else t = a; // 否则在校友里面找
string maxbirth = "99999999", maxid; // maxbirth: 最年长的人的生日, maxid: 最年长的人的身份证号
for (auto e : t) // 遍历t
{
if (!b.count(e)) continue; // 如果没有参加校庆就跳过
string birth = e.substr(6, 8); // 提取生日
if (birth < maxbirth) maxbirth = birth, maxid = e; // 更新答案
}
cout << maxid; // 输出
return 0;
}
迭代器版代码(感谢@陆修远带来的灵感,我做了亿点改进)
#include <iostream>
#include <unordered_set> // unordered_set的头文件
using namespace std;
int n, m;
unordered_set<string> a, b; // a: 所有校友, b: 参加校庆的所有人士
string id;
int main()
{
ios::sync_with_stdio(0); // 提高输入输出速度
cin.tie(0); // 这个也是
cin >> n;
while (n -- ) // 输入所有校友的身份证号
{
cin >> id;
a.insert(id);
}
cin >> m;
while (m -- ) // 输入参加校庆的所有人士的身份证号
{
cin >> id;
b.insert(id);
}
int cnt = 0; // cnt: 多少校友来了
for (auto e : b) // 遍历b
cnt += a.count(e);
cout << cnt << '\n'; // 输出
auto first = b.begin(), last = b.end(); // first: 要寻找区间的开始, last: 要寻找区间的结束. 如果没有校友来,就在参加校庆的所有人士里面找答案
if (cnt) first = a.begin(), last = a.end(); // 否则在校友里面找
string maxbirth = "99999999", maxid; // maxbirth: 最年长的人的生日, maxid: 最年长的人的身份证号
for (auto it = first; it != last; it ++ ) // 遍历区间
{
if (!b.count(*it)) continue; // 如果没有参加校庆就跳过
string birth = (*it).substr(6, 8); // 提取生日(注意优先级,.的优先级要比*高)
if (birth < maxbirth) maxbirth = birth, maxid = *it; // 更新答案
}
cout << maxid; // 输出
return 0;
}
第一次见这个unordered_set,感觉很好用,以后可以和vector换着用了,感谢大佬。
刷过pta全题,pta的题目描述确实是反人类的.
xxs太强啦
Orz
过分
…
小白问一下:a.count(e)是什么意思?
e
在集合a
中出现的次数哦,谢谢解答