B.小Z来讲排名规则 | 2018 校内选拔赛 练习赛

Description

本次比赛严格按照ACM的排名规则进行,但可能很多小伙伴并不太了解这个排名方法,今天小Z来给大家简单说明一下。每个人的排名根据他解出的题目数量、做题时间还有错误提交次数决定,呃。。。在某些特殊情况下跟大家的昵称也有关系哟~不过不要着急去改昵称,毕竟是特殊情况,很难遇到的。下面我具体说明一下。

  1. 排名的第一关键字是解出的题目数,也就是说,解出题目数量多的小伙伴一定会排在解出题目数量少的小伙伴前面
  2. 如果解出的题目数量相同,则根据“罚时”决定排名,罚时少者靠前。罚时是这样定义的:每道成功解出的题目会造成罚时,其他题目不会;每道成功解出的题目造成的罚时是成功解出该题的时间,加上错误提交次数20分钟(比如一道题目在第30分钟解出,之前错误提交了两次,那么总的罚时就是30+20*2=70分钟,这里的错误指的是除了Accept之外的所有反馈情况);最终的罚时是所有成功解出题目的罚时的总和。

  3. 一道题目正确解出后,再次提交无论结果如何,都不会再对罚时产生任何影响。

  4. 如果解出的题目数量和罚时数量都相同,在这个平台上就会按照昵称排序。

举个例子,比如当前有5道题目,你成功解出了1,3,5号题目,1号题目在第5分钟1次解出,第3号题目在第10分钟尝试了一次但是wa了,在第15分钟解出;第5号题目在第20分钟解出,之后你又提交了2次;第2号题目你尝试了4次但是都没有解出;第4号题目你没有尝试。那么最终你的罚时是5 + 0 + 15+1*20 + 0 + 20 = 60分钟,你解出了3道题。假设此时有另外三个小伙伴A,B,C,成绩分别是4题75分钟,3题90分钟,2题20分钟,那么最终的排名是A,你,B,C。

好了,现在给你一些提交记录,按照这个规则试着计算一下吧。

Input

第一行包含一个整数T,代表数据组数。
接下来包含T组测试数据。
每组数据第一行包含三个整数n,m,q,分别代表参赛人数、题目数量、提交记录数量。(1<=n,m,q<=10)
紧接着q行,每行包含4个整数p,t,r,s,意思是p号小伙伴在第t分钟提交了r号题目,得到了s的反馈,若s==0则代表错误,s==1代表正确。注意,你的编号就是1号。其他编号的小伙伴只是陪你一起打比赛玩耍的~(1<=p<=n,1<=t<=100,1<=r<=m,s=0或者s=1)
输入保证不存在两个选手,其通过题目数量和罚时相同。

Output

对于每组测试样例,输出一行包含三个整数,分别代表你(1号)的排名、做出的题目数量和罚时。

Sample Input

1
2 5 10
1 5 1 1
1 6 2 0
1 7 2 0
1 8 2 0
1 9 2 0
1 10 3 0
1 15 3 1
1 20 5 1
1 30 5 1
1 35 5 0

Sample Output

1 3 60

Hint

通过结构体数组存储数据,使用cmp函数调用sort对结构体数组进行排序。

题解

#define N 20
#include "cstdio"
#include "cstring"
#include "cstdlib"
#include "iostream"
#include "cmath"
#include "algorithm"
using namespace std;

struct Problem
{
    int time[N];//各用户错误次数
}problem[N];

struct Member
{
    int sum;//AC次数
    int time;//罚时
    int num;//编号
}member[N];

/**
 * 排名关键字权重
 * 1. AC个数
 * 2. 罚时 = 解出时间 + 20 * 错误提交个数,只有AC才会计算罚时
 * 3. 昵称(不考虑)
 */

inline bool cmp(Member A, Member B)
{
    //名次从高向低排列
    if (A.sum < B.sum || (A.sum == B.sum && A.time > B.time))
            return 0;
    return 1;
}

int main()
{
    //std::ios_base::sync_with_stdio(false);
    //std::cin.tie(0);
    //srand((unsigned int)(time(NULL)));
    int T;
    scanf("%d", &T);//T组样例
    for (int Case = 0; Case < T; Case++)
    {
        /**
         * n 参赛人数
         * m 题目数量
         * q 提交记录数量
         */
        int n, m, q;
        scanf("%d%d%d", &n, &m, &q);
        //标记编号方便查询自己
        for (int i = 1; i <= n; i++)
            member[i].num = i;

        for (int i = 0; i < q; i++)
        {
            int p, t, r, s;
            /**
             * p 选手id
             * t 解出时间
             * r 题目编号
             * s 返回结果 0 错误 1 正确
             */
            scanf("%d%d%d%d", &p, &t, &r, &s);
            if (s)
            {
                //正确
                //处理多次提交正确结果
                if (problem[r].time[p] != -1)
                {
                    member[p].sum++;
                    member[p].time += t + 20 * problem[r].time[p];
                    problem[r].time[p] = -1;//做标记
                }
            }
            else
            {
                //错误
                //处理做对后故意做错
                if (problem[r].time[p] != -1)
                    problem[r].time[p]++;
            }
        }
        sort(member + 1, member + n + 1, cmp);
        for (int i = 1; i <= n; i++)
        {
            if (member[i].num == 1)
            {
                printf("%d %d %d\n", i, member[i].sum, member[i].time);
                break;
            }
        }
        memset(problem, 0, sizeof(problem));
        memset(member, 0, sizeof(member));
    }
    
    return 0;
}

CC BY-SA 4.0 B.小Z来讲排名规则 | 2018 校内选拔赛 练习赛 by 小小泥娃 is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

发表评论

This site uses Akismet to reduce spam. Learn how your comment data is processed.