高考排名
- R a n k i n g Ranking Ranking
I w a s e v e r a f i g h t e r , s o , o n e f i g h t m o r e , t h e b e s t a n d t h e l a s t . I \ was \ ever \ a \ fighter, \ so, \ one \ fight \ more, \ the \ best \ and \ the \ last. I was ever a fighter, so, one fight more, the best and the last.
1. D e s c r i b e 1.Describe 1.Describe
高考成绩的排名规则是按总分由高到低排,总分相同的人排名应相同,例如有 5 5 5 个同学的高考成绩:
考号 姓名 成绩 001 001 001 c 1 c1 c1 567 567 567 002 002 002 y g h ygh ygh 605 605 605 003 003 003 g l gl gl 690 690 690 004 004 004 x t b xtb xtb 605 605 605 005 005 005 w z s wzs wzs 567 567 567 按照成绩排序后,成绩如下:
排名 考号 姓名 成绩 1 1 1 003 003 003 g l gl gl 690 690 690 2 2 2 002 002 002 y g h ygh ygh 605 605 605 2 2 2 004 004 004 x t b xtb xtb 605 605 605 3 3 3 001 001 001 c 1 c1 c1 567 567 567 3 3 3 005 005 005 w z s wzs wzs 567 567 567 现在给出 n n n 个同学的高考成绩信息,请你回答查询:考号为 xxx 的学生排名是多少。
输入第一行含一个整数 n n n,表示学生人数。
接下来的 n n n 行,每行表示一个学生信息:考号(长度为 6 6 6 的数字串),姓名(长度不超过 10 10 10,且不空格的字符串),成绩(是在 0 ⋯ 750 0\cdots 750 0⋯750 之间的整数)。
第 n + 2 n+2 n+2 行为一个整数 m m m,表示有 m m m 次查询。接下来的 m m m 行,每行是一个考号信息。输出包含 m m m 行,对应输入中的查询。如果找到对应考号的学生,输出其姓名和名次,否则输出“ T e s t e r r o r n u m b e r ! Test \ error \ number! Test error number!”。
2. S a m p l e 2.Sample 2.Sample
( i n p u t ) (input) (input)
5
001 cl 567
002 ygh 605
003 gl 690
004 xtb 605
005 wzs 567
3
003
001
006
( o u t p u t ) (output) (output)
gl 1
cl 3
Test error number!
3. S o l u t i o n 3.Solution 3.Solution
这道题用的是 S T L STL STL。(废话)
我的方法是用 m a p map map (映射)和 p r i o r i t y q u e u e priority \ queue priority queue (优先队列) 。
在输入的过程中,由于要进行排序,马上就会想到优先队列。在最后的输出时,学号和下标存在键-值的对应关系,可以用 m a p map map 。
我的代码(别急):
#include <cstdio>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <iostream>
#pragma GCC optimize(2)
using namespace std;
struct student {
string number;
char name[15];
int grades, order, id;
// int text;
bool operator<(const student& x)const {
return grades < x.grades;
}
} a[100005];
//bool cmp(student x, student y) {
// return x.grades > y.grades;
//}
map<string, int> g;
priority_queue<student, vector<student>, less<student> > pq;
int main() {
ios::sync_with_stdio(false);
int n;
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> a[i].number >> a[i].name >> a[i].grades;
a[i].id = i;
g[a[i].number] = i;
// cout << "map:" << g[a[i].number] << " ";
pq.push(a[i]);
}
// cout << endl;
int tmp = 0;
int id;
while(!pq.empty()) {
if(pq.top().grades != tmp) {
id ++;
a[pq.top().id].order = id;
}
else {
a[pq.top().id].order = id;
}
tmp = pq.top().grades;
// a[i].text = tmp;
pq.pop();
}
// for(int i = 1; i <= n; i ++) {
// cout << "order:" << a[i].order << " ";
// }
// cout << endl;
int q;
cin >> q;
while(q --) {
string s;
cin >> s;
// cout << "map:" << g[s] << " ";
g[s] ? cout << a[g[s]].name << " " << a[g[s]].order << endl : cout << "Test error number!" << endl;
}
return 0;
}
(注释有点多)
我们分开来讲。
p a r t I part\ I part I
struct student {
string number; //学号
char name[15]; //姓名
int grades, order, id; //成绩,排名后的名次,输入时的下标。
// int text;
bool operator<(const student& x)const { //重载运算符
return grades < x.grades;
}
} a[100005];
这里设置了变量 i d id id,因为之后会进行排序,通过 i d id id 可以还原原数组。
这里也有重载运算符操作,主要是方便后面优先队列的排序。
p a r t I I part \ II part II
map<string, int> g; //映射
priority_queue<student, vector<student>, less<student> > pq; //优先队列
map<string, int> g
通俗讲就是下标类型为 string
而数据类型为 int
(一个字符串对应一个整数)。这里下标为学号,存的是下标(学号)在原数组里的下标。
比如说一个人叫 张三,他是第
3
3
3 输入的,则 g[张三]=3
。
priority_queue<student, vector<student>, less<student> > pq
可以看做一个可以排序的队列,push
一个就找个合适的地方存放。其中 less
表示从大到小,此外还有从小到大的 greater
。
p a r t I I I part \ III part III
for(int i = 1; i <= n; i ++) {
cin >> a[i].number >> a[i].name >> a[i].grades;
a[i].id = i;
g[a[i].number] = i;
// cout << "map:" << g[a[i].number] << " ";
pq.push(a[i]);
}
输入。
a[i].id = i
,备份下标。
g[a[i].number] = i;
,建立对应关系。
pq.push(a[i])
,插入元素,同时排序。
p a r t I V part\ IV part IV
int tmp = 0;
int id;
while(!pq.empty()) {
if(pq.top().grades != tmp) {
id ++;
a[pq.top().id].order = id;
}
else {
a[pq.top().id].order = id;
}
tmp = pq.top().grades;
// a[i].text = tmp;
pq.pop();
}
排名。
相当于把队列里的一个一个拎出来。
tmp
表示一个被比较的数(上一个人考的分数),当这个人和上一个人考的一样,他的排名就应该和上一个人一样,反之是上一个人的排名加
1
1
1。之后将这个人考的分数赋值给 tmp
,继续比较。
注意:
a[pq.top().id]
,在这里之前备份的下标有用了。
p a r t V part\ V part V
int q;
cin >> q;
while(q --) {
string s;
cin >> s;
// cout << "map:" << g[s] << " ";
g[s] ? cout << a[g[s]].name << " " << a[g[s]].order << endl : cout << "Test error number!" << endl;
}
输出。
询问一个学号,输出对应的姓名和排名,这里 g[s]
对应的是原数组的对应下标,如果 g[s]
为
0
0
0 的话,说明 s
未与任何人对应,即没有该考生的信息,输出
T
e
s
t
e
r
r
o
r
n
u
m
b
e
r
!
Test \ error \ number!
Test error number! 。
小提示:
O2
是要开的。
(
b
e
f
o
r
e
)
(before)
(before)
(
a
f
t
e
r
)
(after)
(after)
显而易见。