【PAT A-1012】The Best Rank

【PAT A-1012】The Best Rank

题意概述

给出多个学生的 ID 以及 C、M、E 这三门课程的成绩,A 代表 C、M、E 这三门课程的平均成绩。输入一个学生 ID,要求输出该学生的 A、C、M、E 这 4 门成绩在所有学生中最高排名。

输入输出格式

先输入 N 和 M,代表有 N 个学生以及 M 个查询。之后的 N 行,每行按“ID C M E”的格式给出一个学生的 ID 以及 C、M、E 这三门课程的成绩。之后 M 行,每行给出一个学生的 ID。

输出 M 行,每行输出给定学生的 A、C、M、E 这 4 门成绩在所有学生中最高排名以及对应科目。如果该 ID 不存在,输出N/A

数据规模

0 < N , M ≤ 2000 0<N,M\le 2000 0<N,M2000,学生 ID 为 6 位数字。

算法设计

先定义unordered_map<gg, unordered_map<char, gg>> rank用来存储学生的 ID 以及对应的 ACME 这四科排名。注意这里的 rank 是一个嵌套的 unordered_map,rank 的键是一个 gg 类型,存储学生的 ID;rank 的值又是一个 unordered_map,它的键是一个 char 类型,负责存储 ACME 字符,它的值负责存储该科目的排名。

再定义一个unordered_map<char, vector<pair<gg, double>>> acme存储四门科目以及对应的所有学生成绩。注意 acme 也是一个 unordered_map,它的键存储 ACME 字符,它的值是一个 vector,存储不同的 pair,这些 pair 的 first 成员是 gg 类型,存储学生的 ID,second 成员是一个 double,存储该学生在该科目上的成绩。注意由于平均成绩可能是小数,因此可以直接将所有成绩均用 double 存储。

读取所有学生的 ID 和成绩并存入 acme 中,针对 acme 中学生成绩进行排序,然后计算每名学生的排名并存入 rank 中。然后针对每个查询,直接在 rank 中查找每个学生的最高排名即可。

具体实现可参考下面的代码。

注意点

具有相同成绩的学生应有相同的排名。

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    gg ni, mi, id, gi;
    cin >> ni >> mi;
    //学生ID以及对应的ACME排名
    unordered_map<gg, unordered_map<char, gg>> rank;
    // ACME每科目分别对应的所有学生成绩
    unordered_map<char, vector<pair<gg, double>>> acme;
    for (gg i = 0; i < ni; ++i) {
        cin >> id;
        double sum = 0;
        for (char c : {'C', 'M', 'E'}) {  //读取三门成绩并放入acme中
            cin >> gi;
            sum += gi;
            acme[c].push_back({id, gi});
        }
        acme['A'].push_back({id, sum / 3.0});  //求平均成绩
    }
    for (auto& i : acme) {
        auto& c = i.first;  // c存储当前处理的科目
        auto& grade = i.second;  // grade处理该科目所有学生的成绩
        sort(grade.begin(), grade.end(),
             [](const pair<gg, double>& p1, const pair<gg, double>& p2) {
                 return p1.second > p2.second;
             });  //按成绩从大到小排序
        gg r = 1;
        for (gg j = 0; j < grade.size(); ++j) {  //求出所有学生在该科目上的排名
            if (j == 0 or abs(grade[j].second - grade[j - 1].second) > 1e-6) {
                r = j + 1;
            }
            rank[grade[j].first][c] = r;
        }
    }
    for (gg i = 0; i < mi; ++i) {  //处理m个查询
        cin >> id;
        if (not rank.count(id)) {  // ID不存在
            cout << "N/A\n";
            continue;
        }
        char c = 'A';
        for (char j : {'A', 'C', 'M', 'E'}) {  //求该学生最高排名的科目
            if (rank[id][j] < rank[id][c]) {
                c = j;
            }
        }
        cout << rank[id][c] << " " << c << "\n";
    }
    return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我真的不是cjc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值