前言
此时(发题解的时候)距离 csp-2023 复赛仅剩不到 1 天。
题意
题目连接-洛谷P7072 [CSP-J2020] 直播获奖
NOI2130 即将举行。为了增加观赏性,CCF 决定逐一评出每个(共
n
(
n
≤
1
0
5
)
n(n \leq 10^5)
n(n≤105))选手的成绩(
a
i
a_i
ai),并直播即时的获奖分数线。本次竞赛的获奖率为
w
(
1
≤
w
≤
99
)
w(1 \leq w \leq 99)
w(1≤w≤99) %,即当前排名前
w
w
w % 的选手的最低成绩就是即时的分数线。如果我们用
j
h
jh
jh 表示计划录取选手,这
j
h
=
max
(
1
,
⌊
w
×
i
100
⌋
)
jh = \max(1,\lfloor \frac{w \times i}{100} \rfloor)
jh=max(1,⌊100w×i⌋)(
i
i
i 表示当前评测到第
i
i
i 个人的成绩)。如有选手成绩相同,则所有成绩并列的选手都能获奖,因此实际获奖人数可能比计划中多。
作为评测组的技术人员,请你帮 CCF 写一个直播程序。
思路
显而易见,每次排序 a a a 数组需要的时间过于久。观察到 w i w_i wi 的范围很小,我们可以用 n u m i num_i numi 表示第 i i i 分共有几个人。每次输入 a i a_i ai 我们就将 n u m a i ← n u m a i + 1 num_{a_i} \gets num_{a_i} + 1 numai←numai+1。
查找时,我们从 600 600 600 开始枚举分数,并记录 h j r hjr hjr 为已经获奖的人数。对于每次查询分数,我们将 h j r ← h j r + n u m j hjr \gets hjr + num_j hjr←hjr+numj,并判断如果 h j r ≥ n u m j hjr \geq num_j hjr≥numj 输出 j j j 即可。
代码
#include<bits/stdc++.h>
using namespace std;
int n,w,a[100005],num[605];
signed main() {
scanf("%d %d",&n,&w);
for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
for(int i = 1;i <= n;i++) {
num[a[i]]++;
int jh = max(1,i * w / 100),hjr = 0;
for(int j = 600;j >= 0;j--) {
hjr += num[j];
if(hjr >= jh) {
printf("%d ",j);
break;
}
}
}
return 0;
}