10-排序5 PAT Judge (25分)

来源:互联网 发布:淘宝卖家货款多久到账 编辑:程序博客网 时间:2024/05/19 12:15

排序规则:

1. 总分相同,名次相同。

2. 总分相同,按照完全正确的题目数量排序。

3. 1、2一致,根据id排名。

4. 没有通过编译的,或者没有得分的,不列出。

5. 保证至少有一个人能出现在排名表上。


特别要注意的是,id的初始值问题一开始没留心这个问题,一个测试用例过不去,纠结了好久。

id的初始值为0,意味着,它会被排在所有总分为0的学生前面!因此,id需要初始化为最大值

想用cin读取3 * 10^5数量的数据果然还是不太科学,o(╯□╰)o,各种改动,有时能够通过,但是并不能保证一定能通过测试。

把所有的cin和cout都换成scanf和prinf,50+ms就能通过数据量最大的测试用例。有所变动的话,大概也会在30+ ~ 70+这个幅度内波动吧。

#include <iostream>#include <algorithm>using namespace std;const int MAXID = 100001;//无法在数组中使用带参构造器,因此全局化这三个变量。//或者不使用构造函数初始化成员变量,直接初始化。这是个人对类的执念。 int n, k, m; struct Student {Student():id(MAXID),totalScore(0),perfectNum(0){scores = new int[k + 1];for(int i = 1; i <= k; ++i)scores[i] = -1;}//重载<运算符,定义比较规则。传入sort的比较器需要是const。     bool operator<(const Student &other) const {        if(totalScore != other.totalScore) return totalScore > other.totalScore;        if(perfectNum != other.perfectNum) return perfectNum > other.perfectNum;        return id < other.id;    }    //定义输出格式。     void print() {    printf("%05d %d", id, totalScore);    for(int i = 1; i <= k; ++i)    scores[i] < 0 ? cout << " -" : cout << " " << scores[i];    cout << endl;}//更新总分。需要更快的话,可以把总分的更新写到main的输入循环中。void updateTotalScore() {for(int i = 1; i <= k; ++i)if(scores[i] > 0) totalScore += scores[i];}int id;int *scores;int totalScore;int perfectNum;};int main(void) {    cin >> n >> k >> m;    //记录每道题的总分,下标1表示第一题。     int *fullMark = new int[k + 1];    for(int i = 1; i <= k; ++i) cin >> fullMark[i];    //下标从1开始,表示一个学生。    Student *pStu = new Student[n + 1];    //作为列表名单的计时器,记录应该被列出的学生数量。    int listNum = 0;    int id, question, score;     for(int i = 0; i < m; ++i) {        scanf("%d%d%d", &id, &question, &score);         //score全为为-1的学生不被列出,因此只需要标记一下。        if(score == -1) {                 if(pStu[id].scores[question] < 0)//若这个值没有被更新过(是初始值),更新为0.                 pStu[id].scores[question] = 0;//标记为0,而不是-1,于是就可以直接输出了。             continue;//在这种设计下,scores[?]可以初始为任一负数。        }        //score >= 0 的情况,学生会被列出。        if(pStu[id].id == MAXID) {//新增一个需要被列出的学生。             ++listNum;//更新listNum             pStu[id].id = id;//并把该“新生”的id赋值为正确的id。         }         if(score > pStu[id].scores[question]) {        //可以在这里更新总分。             pStu[id].scores[question] = score;            if(score == fullMark[question])                ++pStu[id].perfectNum;        }    }    //更新总分后排序。     for(int i = 1; i <= n; ++i)pStu[i].updateTotalScore();     sort(pStu + 1, pStu + n + 1);    //输出    int rank = 1;    int lastTotal = pStu[1].totalScore;     for(int i = 1; i <= listNum; ++i) {    //lastTotal的初始值是什么无关紧要,总可以在这里赋上正确值。        if(pStu[i].totalScore < lastTotal) {            rank = i;            lastTotal = pStu[i].totalScore;        }        cout << rank << " ";         pStu[i].print();    }    //虽然用固定数组操作起来方便点,但我总是喜欢使用动态数组。o(╯□╰)o     delete[] fullMark;    delete[] pStu;     return 0;}





0 0