PAT 准考证号由 4 部分组成:
- 第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级;
- 第 2~4 位是考场编号,范围从 101 到 999;
- 第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位;
- 最后 11~13 位是考生编号,范围从 000 到 999。
现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。
输入首先在一行中给出两个正整数 N 和 M,分别为考生人数和统计要求的个数。接下来 N 行,每行给出一个考生的准考证号和其分数(在区间[0,100]内的整数),其间以空格分隔。考生信息之后,再给出 M 行,每行给出一个统计要求,格式为:类型 指令
,其中:
- 类型为 1 表示要求按分数非升序输出某个指定级别的考生的成绩,对应的指令则给出代表指定级别的字母;
- 类型为 2 表示要求将某指定考场的考生人数和总分统计输出,对应的指令则给出指定考场的编号;
- 类型为 3 表示要求将某指定日期的考生人数分考场统计输出,对应的指令则给出指定日期,格式与准考证上日期相同。
对每项统计要求,首先在一行中输出
Case #: 要求
,其中#
是该项要求的编号,从 1 开始;要求
即复制输入给出的要求。随后输出相应的统计结果: - 类型为 1 的指令,输出格式与输入的考生信息格式相同,即
准考证号 成绩
。对于分数并列的考生,按其准考证号的字典序递增输出(题目保证无重复准考证号); - 类型为 2 的指令,按
人数 总分
的格式输出; - 类型为 3 的指令,输出按人数非递增顺序,格式为“考场编号 总人数”。若人数并列则按考场编号递增顺序输出。
如果查询结果为空,则输出
NA
。
使用好 pair、vector、unordered_map 和 sort 即可解决本题。
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
using psg = pair<string, gg>;
//存储T、A、B级别下的考生,处理类型1的要求
unordered_map<char, vector<psg>> c1;
//存储考场中的人数和总分,处理类型2的要求
unordered_map<string, array<gg, 2>> c2;
//存储日期下考场中的人数,处理类型3的要求
unordered_map<string, unordered_map<string, gg>> c3;
gg ni, mi, ci, score;
string si;
cin >> ni >> mi;
for (gg i = 0; i < ni; ++i) { //读取准考证和成绩
cin >> si >> score;
c1[si[0]].push_back({si, score}); //将该考生插入到对应级别中
auto& p = c2[si.substr(1, 3)];
++p[0]; //递增考场人数
p[1] += score; //更新考场总分
++c3[si.substr(4, 6)][si.substr(1, 3)]; //递增日期、考场中的人数
}
auto cmp = [](const psg& s1, const psg& s2) { //比较函数
return tie(s2.second, s1.first) < tie(s1.second, s2.first);
};
for (gg i = 1; i <= mi; ++i) {
cin >> ci >> si;
cout << "Case " << i << ": " << ci << " " << si << "\n";
if ((ci == 1 and c1.count(si[0])) or (ci == 3 and c3.count(si))) {
auto v = ci == 1 ? c1[si[0]] : vector<psg>(c3[si].begin(), c3[si].end());
//排序,注意类型1和类型3的比较函数是一样的
sort(v.begin(), v.end(), cmp);
for (auto& j : v) {
cout << j.first << " " << j.second << "\n";
}
} else if (ci == 2 and c2.count(si)) {
cout << c2[si][0] << " " << c2[si][1] << "\n";
} else {
cout << "NA\n";
}
}
return 0;
}