题目大意:给出各个赛点的成绩单,求总的排行榜。给出n表示赛点个数,每个赛点给出k表示该赛点的选手人数,接下来k组数据,每组包含选手注册号和成绩。总的排行榜按照成绩降序,若成绩相同则注册号小的排在前面。每个选手在排行榜中的信息包括该选手的总排名、赛点号和赛点排名。
思路:
- 总排名只需将所有人按照成绩和注册号统一排序即可得到。
- 给各个赛点依次进行排序,再将赛点排名更新到总排行榜中显然会超时,因此对于赛点排序需要特殊处理。
- 在总排行榜中,每个人的赛点号是易得到的,那么对于每个赛点都去维护一个rk,代表该赛点在当前排行榜中出现的人的个数,同时在每个赛点中再设置一个map<int,int>来映射每个成绩的名次,这样对于之前已经出现过相同成绩的选手可得到对应的赛点排名。
- 避免骚操作,一句ios::sync_with_stdio(false);导致三个段错误、一个答案错误。PAT经典玄学问题!
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N=1e2+5;
const int M=3e2+5;
struct Node{
string name;
int sc,fr,ln,lr;
} board[N*M];
int rk[N];
map<int,int> mp[N];
bool cmp(const Node &a,const Node &b){
if(a.sc==b.sc) return a.name<b.name;
return a.sc>b.sc;
}
int main()
{
int n,k,cnt=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&k);
for(int j=0;j<k;j++){
cin>>board[cnt].name>>board[cnt].sc;
board[cnt].ln=i+1;
cnt++;
}
}
sort(board,board+cnt,cmp);
printf("%d\n",cnt);
for(int i=0;i<cnt;i++){
board[i].fr=(!i||board[i].sc!=board[i-1].sc)? i+1:board[i-1].fr;
int ln=board[i].ln;
rk[ln]++;
if(mp[ln][board[i].sc]) board[i].lr=mp[ln][board[i].sc];
else{
board[i].lr=rk[ln];
mp[ln][board[i].sc]=rk[ln];
}
printf("%s %d %d %d\n",board[i].name.c_str(),board[i].fr,ln,board[i].lr);
}
return 0;
}