牛客网处女座与cf-(模拟)

链接:https://ac.nowcoder.com/acm/contest/327/B
来源:牛客网

题目描述

众所周知,处女座经常通过打cf来调节自己的心情。今天处女座又参加了一场cf的比赛,他知道了所有的提交记录,他想知道自己的得分和排在第几名。你知道处女座的cf账号是cnz


Codeforces规则如下:

1.       比赛一共2小时

2.       比赛有5题,A题500分,B题1000分,C题1500分,D题2000分,E题2500分。

3.       得分规则如下:

在第0分钟完成某一题可以得到全部的分数,每过一分钟每题的分值会衰减1/250,比如在第3分钟完成A题,能够得到500-2*3=494分

4.       如果一道题是的返回结果WA或者TLE被称为错误的提交,CE视为无效的提交,AC,WA和TLE 都视为有效的提交。如果一道题你最后通过了,你会得到这道题衰减之后的分值再减去你错误提交次数*50,就是每次错误的提交会有50分的罚时。

5.       如果你通过了一道题,你的得分不会低于该题分值的30%。比如你在第50分钟通过了A,你有7次错误的提交,你的得分为max(500*0.3,500-2*50(得分衰减)-7*50(错误提交的罚时))=150分。

6.       由于hack机制的存在,你每进行一次提交,对于这一题之前的有效提交(AC,WA,TLE)都视为错误的提交。

7.       一个人只有提交(AC,WA,TLE,CE)过代码,才被视为参加比赛。


处女座又了解到一些信息:

本场比赛没有任何选手hack别人,并且没有任何的提交fst(即只要是某题的最后一次提交通过,就视为通过这道题)

输入描述:

第一行两个整数n和m,n为报名比赛的人数,m为提交的个数
接下来n行,每行一个字符串,表示报名比赛的人的昵称。(字符串只包含小写字母,且长度小于20)
接下来m行,每行的格式为Time,Submiter,Problem,Verdict。
Time为提交的时间,是1到120中的一个正整数(包含1和120),保证Time按顺序给出
Submiter为提交者昵称
Problem为题目名称,是’A’,’B’,’C’,’D’,’E’中的一个字母。
Verdict为返回的结果,为”AC”,”WA”,”TLE”,”CE”中的一个。
2<=n<=500
1<=m<=10000

输出描述:

如果处女座参加了比赛,输出两行:
第一行为处女座的得分
第二行格式x/y,其中x为处女座的排名,y为参加比赛的总人数。如果分数相同那么排名并列。
如果处女座没有参加比赛,输出”-1”
示例1

输入

3 7
cnz
cuber
moon
3 cnz A AC
5 cuber A AC
6 cnz B CE
10 cuber C AC
20 cnz B AC
30 cuber D TLE
100 cnz E AC

输出

2914
1/2
题目的坑:(能用人话讲清楚的,非要用鬼话)
1.以最后一次提交作为结果,比如ac之后又wa,当作wa
2.提交ce是无效提交,不扣分,但是可以认为参加了比赛
3.ac之后又ac,上次的ac作为错误提交,相当于wa
4.关系错综复杂,要正确处理好各自的关系,用映射解决提交过程中选手的编号
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<set>
#include<string>
#include<sstream>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

map<string,int>mp;//参赛选手对应编号以方便查找数组下标
int ans[505];//最终分数
int ac[505][10];
int wa[505][10];
bool flag[505];//是否参赛
int main()
{
    memset(ans,0,sizeof(ans));
    memset(ac,-1,sizeof(ac));//初始化没有ac的状态为-1,如果ac则改为ac的时间
    memset(wa,0,sizeof(wa));
    memset(flag,false,sizeof(flag));
    int n,m; string s;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        mp[s]=i;
    }
    int t; char p; string v;
    for(int i=1;i<=m;i++)
    {
        cin>>t>>s>>p>>v;
        flag[ mp[s] ]=true;//确定为参赛
        if(v[0]!='A')//wa
        {
            if(ac[mp[s]][p-'A']!=-1) //ac过,犯贱让它wa了
            {
                ac[mp[s]][p-'A']=-1;//重新置为没有ac
                wa[mp[s]][p-'A']++;//wa次数+1,上次ac当作wa处理,
            }
                wa[mp[s]][p-'A']++;//本次又是一发wa
        }
        else    //ac
        {
            if(ac[mp[s]][p-'A']!=-1)//ac后又ac
            {
                wa[mp[s]][p-'A']++;//上一发ac当作wa,wa+1
                ac[mp[s]][p-'A']=t;//更新ac时间
            }
            else//没ac过
            {
                ac[mp[s]][p-'A']=t;
            }
        }
        if(v[0]=='C')//CE是无效提交,前面把它当作有效提交wa处理了
            wa[mp[s]][p-'A']--;
    }
    int num=0;
    for(int i=1;i<=n;i++)
    {
        if(flag[i])
        {
            num++;//统计参赛人数
            for(int j=0;j<=4;j++)//遍历五道题统计分数
            {
                if(ac[i][j]!=-1)//ac的题目才算分
                {
                    int group=500+j*500;//本题分数
                    int minn=group*0.3;//本题至少得分,max函数里不允许用group*0.3
                    int tg=ac[i][j]*(group/250);//因时间问题扣分
                    int wag=wa[i][j]*50;//因wa扣分
                    ans[i]=ans[i]+max(minn,group-tg-wag);//累加参赛选手的总分
                }
            }
        }
    }
    if(!flag[mp["cnz"]])
        printf("-1
");//处女座没参赛输出一行就好
    else
    {
        printf("%d
",ans[mp["cnz"]]);
        int rank=1;//初始化排位为1
        for(int i=1;i<=n;i++)
        {
            //printf("ans[%d]=%d
",i,ans[i]);
            if(ans[i]>ans[mp["cnz"]])
                rank++;//不要去统计排第几,有一人比他高,排名就往后掉
        }
        printf("%d/%d",rank,num);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shoulinniao/p/10321309.html