带模拟。
题意
有N位考生,共有K道题,且每道题的分值给出。然后给出M次提交记录,每个提交记录显示了该次提交所属考生的准考证号、交题的题号及所得的分值,其中分值要么是-1 (表示未通过编译),要么是0到该题满分区间的一个整数。现在要求对所有考生按下面的规则排序:
- 先按K道题所得总分从高到低排序。
- 若总分相同,则按完美解决(即获得题目满分)的题目数量从高到低排序。
- 若完美解决的题目数量也相同,则按准考证号从小到大排序。
输出规则:
- 输出每位考生的排名、准考证号、总分、K道题的各自得分,若总分相等,则排名相同。
- 如果某位考生全场都没有提交记录,或是没有能通过编译的提交,则该考生的信息不输出。
- 对需要输出的考生,如果某道题没有能通过编译的提交,则将该题记为0分;如果某道题没有提交记录,则输出'-'。
思路
为了能区分“全场都没有提交”“没有能通过编译的提交”以及“有能通过编译的提交”三种情况,同时处理需要输出的考生的未通过编译的题记为0分的情况,不妨将每个考生的数组grade[]初始化为-2,来表示该题没有提交。于是对每个提交记录,就可以得到如下处理方式(按顺序执行):
- 如果当前提交能通过编译,则令该考生的shown为true,表示有能通过编译的提交。
- 如果当前提交使该考生获得该题的更高分数,则将这个分数覆盖到已有记录上。
所有提交记录处理完毕后,把需要输出的每个考生的总分和完美解题数计算出来,再进行排序。
最后一步输出需要输出的考生信息。其中,只要某题的得分为-2,则表示该题没有提交,需要输出'-'。
int p[10];
int n,k,m;
struct Node
{
string id;
int grade[10];
int sum;
int solve;
int rank;
bool shown;
Node(){}
Node(string _id):id(_id)
{
for(int i=1;i<=k;i++) grade[i]=-2;
sum=solve=shown=rank=0;
}
bool operator<(const Node &W) const
{
if(sum != W.sum) return sum > W.sum;
if(solve != W.solve) return solve > W.solve;
return id < W.id;
}
};
map<string,Node> mp;
int main()
{
cin>>n>>k>>m;
for(int i=1;i<=k;i++) cin>>p[i];
while(m--)
{
string id;
int problem_id,score;
cin>>id>>problem_id>>score;
if(!mp.count(id)) mp[id]=Node(id);
mp[id].grade[problem_id]=max(mp[id].grade[problem_id],score);
if(score != -1) mp[id].shown=true;
}
vector<Node> res;
for(auto t:mp)
{
if(t.se.shown)
{
for(int i=1;i<=k;i++)
{
t.se.sum+=max(0,t.se.grade[i]);
if(t.se.grade[i] == p[i]) t.se.solve++;
}
res.pb(t.se);
}
}
sort(res.begin(),res.end());
for(int i=0;i<res.size();i++)
{
if(i && res[i].sum == res[i-1].sum)
res[i].rank = res[i-1].rank;
else
res[i].rank=i+1;
cout<<res[i].rank<<' '<<res[i].id<<' '<<res[i].sum;
for(int j=1;j<=k;j++)
if(res[i].grade[j] == -2) cout<<" -";
else cout<<' '<<max(0,res[i].grade[j]);
cout<<endl;
}
//system("pause");
return 0;
}