0题目原文(本地存了一份)
为什么要在这儿抄一份题面
原题在洛谷上(页头有链接)。别人的网站不归我们管,打不开、改版、题号调整都可能发生。 所以每个解析页都把题面转录一份存在本地,跟着仓库一起进版本库。
转录自洛谷 B2159,日期见页头。两边不一致时信原站。
题目描述
给出班里某门课程的成绩单,请你按成绩从高到低对成绩单排序输出,如果有相同分数则名字字典序小的在前。
输入格式
第一行为 $n$($0 < n < 20$),表示班里的学生数目;接下来的 $n$ 行,每行为每个学生的名字和他的成绩,中间用单个空格隔开。名字只包含字母且长度不超过 $20$,成绩为一个不大于 $100$ 的非负整数。
输出格式
把成绩单按分数从高到低的顺序进行排序并输出,每行包含名字和分数两项,之间有一个空格。
输入输出样例
输入
3 Alice 90 Bob 85 Charlie 90
输出
Alice 90 Charlie 90 Bob 85
学生版:一页看懂这道题
这道题考什么:多关键字排序的最小版本 —— 先按分数从高到低,分数相同按名字字典序从小到大。
最容易错的两处
- 把「分数高的在前」写成
return x.score < y.score;,顺序就反了。 - 同分时忘了比名字,或者把名字的比较写反。
能 AC 的:b2159。cmp 里先比分数(降序),分不出高下再比名字(升序)。
下面每一步里灰色的「深入」块是折叠的:那是这些结论怎么实测出来的,第一遍可以跳过。
1直接按 cmp 排
b2159.cpp★ 这一版就能 AC
#include <bits/stdc++.h>using namespace std;
struct Student { string name; int score;};
int main() { int n; if (!(cin >> n)) return 0; vector<Student> a(n); for (int i = 0; i < n; i++) cin >> a[i].name >> a[i].score; sort(a.begin(), a.end(), [](const Student &x, const Student &y) { if (x.score != y.score) return x.score > y.score; return x.name < y.name; }); for (auto &s : a) cout << s.name << " " << s.score << "\n"; return 0;}点一下即可编辑
输入(stdin)
输出
点「运行 ▶」看结果
★ 两行 cmp 就是全部
if (x.score != y.score) return x.score > y.score; —— 分数高的在前。
return x.name < y.name; —— 分数相同,名字字典序小的在前。
⇒ 和第 10 章那句「先分主次,主的分不出高下再看次的」是同一件事。