1012 The Best Rank (25 分)(测试点二)

1012 The Best Rank (25 分)

题目链接

算法分析

优先队列+数组

分四种情况(C、M、E、A)压入优先队列中
然后把每个科目的排名存在各自的数组中
然后每种情况进行查询即可

测试点

测试点二:成绩相同
我虽然注意到了这一点,但是并没有过
原因在于:对于这样一组数据98 95 96 95 92
排名数据为:1 3 2 3 5
而不是:1 3 2 3 4
改过之后就满分了!
在这里插入图片描述

代码实现

#include<bits/stdc++.h>
using namespace std;
#define N 2005
#define T 1000000
char s[5] = {'E', 'M', 'C', 'A'};
typedef struct{
	int Id;
	int Mark_C, Mark_M, Mark_E, Mark_ave;
}STU;
STU stu[N];
priority_queue< int >fro_C, fro_M, fro_E, fro_ave;
int id[T];
int C[T], M[T], E[T], Ave[T];
void work(priority_queue< int > que, int *mp){
	int last = -1, rank = 0, t = 0;;
	while(!que.empty()){
		++ t;
		int x = que.top();
		if(x != last) rank = t;
		mp[x] = rank;
		last = x;
		que.pop();
	}
}
char ans_char;
int Get_ans(int x){
	int Min = 1e8, Min_t;
	if(E[stu[id[x]].Mark_E] <= Min) Min = E[stu[id[x]].Mark_E], Min_t = 0;
	if(M[stu[id[x]].Mark_M] <= Min) Min = M[stu[id[x]].Mark_M], Min_t = 1;
	if(C[stu[id[x]].Mark_C] <= Min) Min = C[stu[id[x]].Mark_C], Min_t = 2;
	if(Ave[stu[id[x]].Mark_ave] <= Min) Min = Ave[stu[id[x]].Mark_ave], Min_t = 3;
	ans_char = s[Min_t];
	return Min;
}
int main(){
	int n, m, x;
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++ i){
		scanf("%d%d%d%d", &stu[i].Id, &stu[i].Mark_C, &stu[i].Mark_M, &stu[i].Mark_E);
		id[stu[i].Id] = i;
		stu[i].Mark_ave = (stu[i].Mark_C + stu[i].Mark_M + stu[i].Mark_E) / 3;
		fro_C.push(stu[i].Mark_C);
		fro_M.push(stu[i].Mark_M);
		fro_E.push(stu[i].Mark_E);
		fro_ave.push(stu[i].Mark_ave);
	}
	work(fro_C, C);
	work(fro_M, M);
	work(fro_E, E);
	work(fro_ave, Ave);
	for(int i = 1; i <= m; ++ i){
		scanf("%d", &x);
		if(!id[x]){
			printf("N/A\n");
			continue;
		}
		int ans = Get_ans(x);
		printf("%d %c\n", ans, ans_char);
	}
	return 0;
}

学习柳诺

柳神的代码思路使用了sort排序
此外有一点我觉得比较值得采用:
在这里插入图片描述
这个题我用了单独的名称和数组,所以看起来就会不太简洁
代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
struct node {
    int id, best;
    int score[4], rank[4];
}stu[2005];
int exist[1000000], flag = -1;
bool cmp1(node a, node b) {return a.score[flag] > b.score[flag];}
int main() {
    int n, m, id;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++) {
        scanf("%d %d %d %d", &stu[i].id, &stu[i].score[1], &stu[i].score[2], &stu[i].score[3]);
        stu[i].score[0] = (stu[i].score[1] + stu[i].score[2] + stu[i].score[3]) / 3.0 + 0.5;
    }
    for(flag = 0; flag <= 3; flag++) {
        sort(stu, stu + n, cmp1);
        stu[0].rank[flag] = 1;
        for(int i = 1; i < n; i++) {
            stu[i].rank[flag] = i + 1;
            if(stu[i].score[flag] == stu[i-1].score[flag])
                stu[i].rank[flag] = stu[i-1].rank[flag];
        }
    }
    for(int i = 0; i < n; i++) {
        exist[stu[i].id] = i + 1;
        stu[i].best = 0;
        int minn = stu[i].rank[0];
        for(int j = 1; j <= 3; j++) {
            if(stu[i].rank[j] < minn) {
                minn = stu[i].rank[j];
                stu[i].best = j;
            }
        }
    }
    char c[5] = {'A', 'C', 'M', 'E'};
    for(int i = 0; i < m; i++) {
        scanf("%d", &id);
        int temp = exist[id];
        if(temp) {
            int best = stu[temp-1].best;
            printf("%d %c\n", stu[temp-1].rank[best], c[best]);
        } else {
            printf("N/A\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Crer_lu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值