CSP-J 2020 T2 直播获奖(洛谷P7072

CSP-J 2020 T2 直播获奖

题目

这道题一开始看很容易想出一个简单的做法,每一次输入完一个分数就从大到小排一下序,然后输出第\(\max(1,\lfloor p*w\% \rfloor)\)个数即可,但时间复杂度为\(O(n^2 \log n)\),有\(n=10^5\)这种恐怖数据的话\(O(n^2 \log n)\)的时间复杂度肯定是无法AC这道题的。

那咋办呢,让我们研究一下数据范围,发现每个选手的成绩均为不超过600的非负整数,那这个范围不是可以用桶排吗?瞬间就变简单了有没有。那么怎么用桶排打出这道题呢?因为第一名是最高分,所以我们从大到小进行遍历,每次让分数线的名次减去取得这个分数的人数,直到分数线的名次小于等于0为止。

这里我用了一个优化,记录最低分和最高分,在这个范围内遍历而不是从600遍历到0,大概能优化几十倍左右。

代码

#include <iostream>
#include <cmath>
using namespace std;
int t[605];
int main()
{
    int n,s,p,mi,ma,w;
    cin>>n>>w;
    for(int i=1;i<=n;++i){
        cin>>s;
        //记录最低分和最高分
        mi=min(mi,s);
        ma=max(ma,s);
        //桶排
        t[s]++;
        //计算分数线是第几名
        p=max(1,i*w/100);
        for(int j=ma;j>=mi;--j){
            //在桶内进行遍历,找到分数线
            p-=t[j];
            //如果找到了就输出
            if(p<=0){
                cout<<j<<' ';
                break;
            }
        }
    }
    return 0;
}
posted @ 2022-03-14 19:13  AC?别闹!  阅读(281)  评论(0编辑  收藏  举报