题目链接:点击这里
题意:每名学生有一个ID 和四个成绩:C(c语言),M(数学),E(英语), A(三门成绩平均值)。每名学生都会有各科排名以及平均成绩排名,我们通过强调学生的最佳成绩来鼓励学生,也就是说,最终只会输出学生四个成绩中排名最好的那个成绩的排名以及相对应的科目(C、M、E、A 中的一项)。
注意:平均成绩为三科成绩平均值四舍五入取整的结果。
思路:由于学生ID是不超过六位的数字,因此可以当作数组下标用来映射和判重。所有同学的单科成绩可能会有相同的,成绩相同的名次也相同,所以,将每科成绩从小到大排序,二分查找最后一个小于等于 x x x 的数组下标,用 N N N 减去下标就是其排名。
例如,对下面数组来说,88分的排名是多少?
最后一个小于等于 88 88 88 的数组下标为 1 1 1,其排名就是 5 − 1 = 4 5-1=4 5−1=4
AC代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
int c, m, e, a;
node() : c(-1), m(-1), e(-1), a(-1){
}
node(int _c, int _m, int _e, int _a) : c(_c), m(_m), e(_e), a(_a){
}
}s[1000010];
int N, M;
int c[20010], m[20010], e[20010], a[20010];
int query(int q[], int x)
{
int l = 0, r = N - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(q[mid] <= x) l = mid;
else r = mid - 1;
}
return N - r;
}
int main()
{
scanf("%d%d", &N, &M);
int id, tc, tm, te, ta;
for(int i = 0; i < N; i++)
{
scanf("%d%d%d%d", &id, &tc, &tm, &te);
ta = round((tc + tm + te) / 3.0);
s[id] = node(tc, tm, te, ta);
c[i] = tc, m[i] = tm, e[i] = te, a[i] = ta;
}
sort(a, a + N);
sort(c, c + N);
sort(m, m + N);
sort(e, e + N);
while(M--)
{
scanf("%d", &id);
if(s[id].c == -1)
{
puts("N/A");
continue;
}
int rank = 1e9;
char course;
int t = query(a, s[id].a);
if(t < rank) rank = t, course = 'A';
t = query(c, s[id].c);
if(t < rank) rank = t, course = 'C';
t = query(m, s[id].m);
if(t < rank) rank = t, course = 'M';
t = query(e, s[id].e);
if(t < rank) rank = t, course = 'E';
printf("%d %c\n", rank, course);
}
return 0;
}
微信公众号《算法竞赛求职》,致力于详细讲解竞赛和求职所涉及到的算法原理和模板。欢迎关注,一起交流进步!