B3968 [GESP202403 五级] 成绩排序
B3968 [GESP202403 五级] 成绩排序 题解
题目链接
题目大意
给定
题目分析
这是一道非常典型的自定义排序的题目,最关键的点就在于输出排名的时候要按照输入顺序输出,且存在日常生活中的“并列占位”情况。
对于这道题来说,我们需要一个结构体储存所有学生的信息:
struct student {
int id, c, m, e, total, highest, sum;
/*id为输入顺序,c,m,e含义如题所述,total记录总分,
highest记录语文和数学的最高分,sum记录语文和数学的总分*/
} a[maxn];
下面一个问题,如何排序呢? 库函数能够支持我们自定义排序方法,可以胜任这道题目:
bool cmp(student a, student b) {//排序代码
if (a.total > b.total) return 1;//比较总分
else if (a.total < b.total) return 0;
else {
if (a.sum > b.sum) return 1;//比较语文数学分数和
else if (a.sum < b.sum) return 0;
else {
if (a.highest > b.highest) return 1;//比较语文数学最高分
else if (a.highest < b.highest) return 0;
else return a.id < b.id;
}
}
}
然后就是这道题最关键的部分:如何正确地输出呢?我们不妨用一个
bool check(int num1, int num2) {//判断是否并列
if (a[num1].total == a[num2].total &&
a[num1].sum == a[num2].sum &&
a[num1].highest == a[num2].highest) return 1;
else return 0;
}
这时候我们就要考虑处理并列的问题了。我们可以定义一个
参考代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
struct student {
int id, c, m, e, total, highest, sum;
/*id为输入顺序,c,m,e含义如题所述,total记录总分,
highest记录语文和数学的最高分,sum记录语文和数学的总分*/
} a[maxn];
int n, p = 1;
//p记录用到了第几个位置
int k;
int ans[maxn], last;
bool cmp(student a, student b) {//排序代码
if (a.total > b.total) return 1;//比较总分
else if (a.total < b.total) return 0;
else {
if (a.sum > b.sum) return 1;//比较语文数学分数和
else if (a.sum < b.sum) return 0;
else {
if (a.highest > b.highest) return 1;//比较语文数学最高分
else if (a.highest < b.highest) return 0;
else return a.id < b.id;
}
}
}
bool check(int num1, int num2) {//判断是否并列
if (a[num1].total == a[num2].total &&
a[num1].sum == a[num2].sum &&
a[num1].highest == a[num2].highest) return 1;
else return 0;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].c >> a[i].m >> a[i].e;
a[i].id = i;
a[i].total = a[i].c + a[i].m + a[i].e;
a[i].highest = max(a[i].c, a[i].m);
a[i].sum = a[i].c + a[i].m;
}
sort(a + 1, a + n + 1, cmp);
ans[a[1].id] = 1;
last = 1;
for (int i = 2; i <= n; i++) {
if (check(last, i)) {//有并列的学生
ans[a[i].id] = p;//记录排名
k++;//是并列的学生,累加k
last = i;
continue;
}
p += k + 1;//并列结束,新的占位
k = 0;//记得清空
ans[a[i].id] = p;//记录排名
last = i;//更新缓存信息
}
for (int i = 1; i <= n; i++ ) {
cout << ans[i] << endl;
}
return 0;
}