1012 The Best Rank (25分)

题意
现已知n个考生的3门课分数C、M、E,而平均分数A可以由这3个分数得到。现在分别按这4个分数对n个考生从高到低排序,这样对每个考生来说,就会有4个排名且每个分数都会有一个排名。接下来会有m个查询,每个查询输入一个考生的ID,输出该考生4个排名中最高的那个排名及对应是A、C、M、E中的哪一个。如果对不同课程有相同排名的情况,则按优先级A>C>M>E输出;如果查询的考生ID不存在,则输出N/A。

毒瘤题。。。之后找机会重写下吧。。。毕竟现在的码风惨不忍睹,而且\(\color{green}{AcWing}\)上只过了\(3\)个点=_=

注意分数相同的同学名次相同,并且小于当前分数的同学的名次依次向后递进。

例如:1、1、3、4、5,而不是1、1、2、3、4。

const int N=2010;
struct Stu {
    int c_rank,m_rank,e_rank,avg_rank;
}a[N];
PII c[N],m[N],e[N];
unordered_map<string,int> mp;
PDI avg[N];
int n,q;


int main()
{
    cin>>n>>q;

    for(int i=0;i<n;i++)
    {
        string id;
        cin>>id>>c[i].fi>>m[i].fi>>e[i].fi;
        avg[i].fi=(c[i].fi+m[i].fi+e[i].fi)/3.0;
        mp[id]=i;
        c[i].se=m[i].se=e[i].se=avg[i].se=i;
    }

    sort(c,c+n,greater<PII>());
    sort(m,m+n,greater<PII>());
    sort(e,e+n,greater<PII>());
    sort(avg,avg+n,greater<PDI>());

    int tot=1;
    for(int i=0;i<n;i++)
    {
        if(i && c[i].fi == c[i-1].fi)
            a[c[i].se].c_rank=a[c[i-1].se].c_rank;
        else
            a[c[i].se].c_rank=tot;
        tot++;
    }
    tot=1;
    for(int i=0;i<n;i++)
    {
        if(i && m[i].fi == m[i-1].fi)
            a[m[i].se].m_rank=a[m[i-1].se].m_rank;
        else
            a[m[i].se].m_rank=tot;
        tot++;
    }
    tot=1;
    for(int i=0;i<n;i++)
    {
        if(i && e[i].fi == e[i-1].fi)
            a[e[i].se].e_rank=a[e[i-1].se].e_rank;
        else
            a[e[i].se].e_rank=tot;
        tot++;
    }
    tot=1;
    for(int i=0;i<n;i++)
    {
        if(i && avg[i].fi == avg[i-1].fi)
            a[avg[i].se].avg_rank=a[avg[i-1].se].avg_rank;
        else
            a[avg[i].se].avg_rank=tot;
        tot++;
    }

    while(q--)
    {
        string id;
        cin>>id;
        if(!mp.count(id))
        {
            puts("N/A");
            continue;
        }
        int x=mp[id];

        int rank=min(min(a[x].c_rank,a[x].m_rank),min(a[x].e_rank,a[x].avg_rank));

        if(a[x].avg_rank == rank)
            cout<<rank<<' '<<'A'<<endl;
        else if(a[x].c_rank == rank)
            cout<<rank<<' '<<'C'<<endl;
        else if(a[x].m_rank == rank)
            cout<<rank<<' '<<'M'<<endl;
        else
            cout<<rank<<' '<<'E'<<endl;
    }


    //system("pause");
    return 0;
}

\(update on 2021.2.14\)
情人节快乐!

思路

  1. 考虑到优先级为A>C>M>E,不妨在设置数组时就按这个顺序分配序号为0 ~ 3的元素,即0对应A、1对应C、2对应M及3对应E。
  2. 按顺序枚举A、C、M、E,对每个分数,将所有考生排序,并在Rank数组中记录排名。
  3. 在查询时,对读入的查询ID,先看其是否存在。如果存在,选出Rank[pos][0] ~ Rank[pos][3]中数字最小(即排名最高)的那个即可。

由于排序会改变\(a\)数组,因此在读入时需要记录下标位置\(pos\),再存储至Rank数组中对应\(pos\)的位置。

注意点

  1. 要注意优先级顺序是A>C>M>E,所以为了方便枚举,在设置数组时尽量把A放在C、M、E前面。
  2. 排名时,相同分数算作排名相同,所以91、90、 88、 88、84的排名应该算作1、2、3、3、5。在具体实现时,切记不要算作1、2、3、3、4。
  3. 本题没有明示平均分是否需要取整以及取整方式,根据题目描述中的例子可以看出是四舍五入。但本题采用向下取整的方式也能通过,或者采用更简洁的方式——不取平均,直接存储三门课的总分。
struct Stu {
    string id;
    int grade[4];
    int pos;
}a[N];
int Rank[N][4];
unordered_map<string,Stu> mp;
char course[]={'A','C','M','E'};
int n,m;
int idx;

bool cmp(Stu &a, Stu &b)
{
    return a.grade[idx] > b.grade[idx];
}

int main()
{
    cin>>n>>m;

    for(int i=0;i<n;i++)
    {
        cin>>a[i].id>>a[i].grade[1]>>a[i].grade[2]>>a[i].grade[3];
        a[i].pos=i;

        for(int j=1;j<4;j++) a[i].grade[0]+=a[i].grade[j];

        mp[a[i].id]=a[i];
    }

    for(idx=0;idx<4;idx++)
    {
        sort(a,a+n,cmp);

        for(int i=0;i<n;i++)
        {
            if(i && a[i].grade[idx] == a[i-1].grade[idx])
                Rank[a[i].pos][idx]=Rank[a[i-1].pos][idx];
            else
                Rank[a[i].pos][idx]=i+1;
        }
    }

    while(m--)
    {
        string id;
        cin>>id;
        if(!mp.count(id)) puts("N/A");
        else
        {
            int pos=mp[id].pos;
            int minidx=0;
            for(int i=1;i<4;i++)
                if(Rank[pos][i] < Rank[pos][minidx])
                    minidx=i;
            cout<<Rank[pos][minidx]<<' '<<course[minidx]<<endl;
        }
    }

    //system("pause");
    return 0;
}

至于\(\color{green}{AcWing}\)上只能过\(3\)个点,\(\color{green}{AcWing}\)上平均成绩为三科成绩平均值四舍五入取整的结果,所以加上下面一行就可以了。

a[i].grade[0]=round(a[i].grade[0]/3.0);
posted @ 2021-01-07 19:09  Dazzling!  阅读(77)  评论(0编辑  收藏  举报