奖学金

GitHub跳转原题关系图返回列表

计算总分后按总分、语文分和学号组成的三元键排序。

OJ: noi_openjudge

题目 ID: ch0110-04

难度:普及-

标签:排序模拟python

日期: 2026-07-30 23:01

题意

每个学生有语文、数学、英语三科成绩。按总分降序、语文降序、学号升序的规则排列,输出前五名的学号和总分。

思路

读入时顺便计算总分,并保存 (学号, 语文, 总分)。排序键为 (-总分, -语文, 学号):前两项取相反数得到降序,学号保持正数得到升序。排序结果前五项就是答案。

代码

Python代码

python
student_count = int(input())
students = []

for student_id in range(1, student_count + 1):
    chinese, math, english = map(int, input().split())
    total = chinese + math + english
    students.append((student_id, chinese, total))

# 总分、语文分取相反数可得到降序;学号保持正数则为升序。
students.sort(key=lambda student: (-student[2], -student[1], student[0]))
for student_id, _, total in students[:5]:
    print(student_id, total)

C++代码

cpp
/* 
 *   快速排序本质:
 *      用key值,把数据分成两个部分,一部分比较key小,一部分比key大
 * */

#include <cstdio>

int n;

struct _stu {
    int yw,sx,yy;
    int idx; //编号
};

_stu a[10010];

// 比较两个学生的大小 , 也就是哪个应该在前面
bool greater( _stu &a,_stu &b){
    int ta = a.yy+a.yw+a.sx;
    int tb = b.yy+b.yw+b.sx;
    if( ta > tb)
        return true;
    
    if( ta == tb  && a.yw > b.yw)
        return true;
    if(ta == tb && a.yw == b.yw && a.idx < b.idx)
        return true;
    if(a.idx == b.idx)
        return true;
    return false;
}

void xchg(_stu &a,_stu &b){
    _stu t = a;
    a = b;
    b =t;
}

void quicksort(int l,int r){

    if( l >= r) return;

    _stu key = a[l];
    int i = l, j = r;
    while( i != j){
        while(greater(key,a[j]) && i < j )
            j--;
        while(greater(a[i],key) && i < j)
            i++;
        if( i < j )
            xchg(a[i],a[j]);
    }

    a[l] = a[i];
    a[i] = key;

    quicksort(l,i-1);
    quicksort(i+1,r);
}

int main(){
	scanf("%d",&n);
	int i,j;
	//输入数据
	for(i=1;i<=n;i++){
	    a[i].idx = i;
	    scanf("%d%d%d", &a[i].yw, &a[i].sx, &a[i].yy);
	}
	quicksort(1,n);

    for(i=1;i<=5;i++)
        printf("%d %d\n",a[i].idx, a[i].yy+a[i].yw+a[i].sx);
    return 0;
}

复杂度

时间复杂度为 O(nlogn)O(n \log n),空间复杂度为 O(n)O(n)

总结

多级排名不必手写比较函数,把各优先级按顺序放进排序键即可。