P7072 [CSP-J2020] 直播获奖(详解)
NOI2130 即将举行。为了增加观赏性,CCF 决定逐一评出每个选手的成绩,并直播即时的获奖分数线。本次竞赛的获奖率为w\%w%,即当前排名前w\%w%的选手的最低成绩就是即时的分数线。更具体地,若当前已评出了pp个选手的成绩,则当前计划获奖人数为\max(1, \lfloor p * w \%\rfloor)max(1,⌊p∗w%⌋),其中ww是获奖百分比,\lfloor x \rfloor⌊
题目提供者 一扶苏一 扶咕咕
难度 普及-
原题网址:点击
题目描述
NOI2130 即将举行。为了增加观赏性,CCF 决定逐一评出每个选手的成绩,并直播即时的获奖分数线。本次竞赛的获奖率为 w\%w%,即当前排名前 w\%w% 的选手的最低成绩就是即时的分数线。
更具体地,若当前已评出了 p 个选手的成绩,则当前计划获奖人数为 max(1, ⌊p * w %⌋),其中 w 是获奖百分比,⌊x⌋ 表示对 x 向下取整,max(x,y) 表示 x 和 y 中较大的数。如有选手成绩相同,则所有成绩并列的选手都能获奖,因此实际获奖人数可能比计划中多。
作为评测组的技术人员,请你帮 CCF 写一个直播程序。
输入格式
第一行有两个整数 n,w。分别代表选手总数与获奖率。
第二行有 nn个整数,依次代表逐一评出的选手成绩。
输出格式
只有一行,包含 n 个非负整数,依次代表选手成绩逐一评出后,即时的获奖分数线。相邻两个整数间用一个空格分隔。
提示
在计算计划获奖人数时,如用浮点类型的变量(如 C/C++ 中的 float
、 double
,Pascal 中的 real
、 double
、 extended
等)存储获奖比例 w\%w%,则计算 5×60% 时的结果可能为3.000001,也可能为 2.999999,向下取整后的结果不确定。因此,建议仅使用整型变量,以计算出准确值。
讲解
好好审审这题,不难发现,输出即时的分数线肯定是输入一个数就输出一个数,而不是全部输完在统一输出,所以不难想出一种算法:先输入,接着存入数组里,接着按降序排一下序,最后输出最后一个获奖的人。
错误代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,w,a[100005],m;
cin>>n>>w;
for(int i=1;i<=n;i++){
cin>>a[i];
m=max(1,i*w/100);
sort(a,a+i,greater<int>());
cout<<a[m]<<" ";
}
return 0;
}
但是我们会发现,这样的代码,只能获得50分,很明显,原因是超时,因为log时间复杂度是n*log2(n),在乘外部的n,整个时间复杂度是n^2*log2(n),n最大10000,log2(10000)大概是13~14左右,10^4的平方*13已超过10^8,所以会超时,我们应该优化,那应该如何优化呢,我们不能再用这个算法了,需要换一个算法。
看来我们不能用数组来分别存每个人的成绩,那么还有什么办法呢?一定是我们忽略了什么关键信息,然后我们会发现一条至关有用的信息:对于所有测试点,每个选手的成绩均为不超过 600 的非负整数,因为成绩共有600个值,那我们不妨存一个下标有600的数组,每个元素存下标的人数。输入完成绩过后,就把下标为输入的数的元素加一,然后从600到0进行一次循环,再定义一个累加的变量,将每个元素的值加入,如果获奖人数大于或等于(因为有可能分数线上有许多人)预期的获奖人数,就输出下标并结束循环。
这道题其实不难,主要的问题是解决超时的问题,解决超时的问题的办法就是优化,
最终代码+注释
#include<bits/stdc++.h>
using namespace std;
int main(){
int x,a[605]={0},n,w,sum;
cin>>n>>w;//输入人数和获奖率
for(int i=1;i<=n;i++){//循环输入
cin>>x;//输入分数
a[x]++;//将得x分的人加一
sum=0;//先将获奖的人数置为0
for(int j=600;j>=0;j--){//计算最后一名获奖的人考了多少分
sum+=a[j];//从高到低计算人数
if(sum>=max(1,i*w/100)){//直到获奖的人数足够
cout<<j<<' ';//输出最后一个获奖的分数
break;//提前结束循环
}
}
}
return 0;
}
好了,那今天就到这里啦,感谢您的支持,有什么不懂的问题也可以写在评论区里,
我们下期再见吧(◕ᴗ◕✿),拜拜(。◕ˇ∀ˇ◕)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)