《【CSP-J2020 基础】直播获奖( live)》 题解

目录

题目描述

输入描述

输出描述

解析

完整代码


描述

NOI2130 即将举行。为了增加观赏性,CCF 决定逐一评出每个选手的成绩,并直播即时的获奖分数线。本次竞赛的获奖率为 w%,即当前排名前 w% 的选手的最低成绩就是即时的分数线。

更具体地,若当前已评出了 p 个选手的成绩,则当前计划获奖人数为 max(1,⌊p×w%⌋),其中 w 是获奖百分比,⌊x⌋ 表示对 x 向下取整,max(x,y) 表示 x 和 y 中较大的数。如有选手成绩相同,则所有成绩并列的选手都能获奖,因此实际获奖人数可能比计划中多。

作为评测组的技术人员,请你帮 CCF 写一个直播程序。

输入描述

第一行有两个整数 n,w。分别代表选手总数与获奖率。
第二行有 n 个整数,依次代表逐一评出的选手成绩。

输出描述

只有一行,包含 n 个非负整数,依次代表选手成绩逐一评出后,即时的获奖分数线。相邻两个整数间用一个空格分隔。

用例输入 1 

10 60
200 300 400 500 600 600 0 300 200 100

用例输出 1 

200 300 400 400 400 500 400 400 300 300

用例输入 2 

10 30
100 100 600 100 100 100 100 100 100 100

用例输出 2 

100 100 600 600 600 600 100 100 100 100

提示

样例 1 解释


数据规模与约定

各测试点的 n 如下表:

测试点编号n=
1∼310
4∼6500
7∼102000
11∼17104
18∼20105

对于所有测试点,每个选手的成绩均为不超过 600 的非负整数,获奖百分比 w 是一个正整数且 1≤w≤99。


提示

在计算计划获奖人数时,如用浮点类型的变量(如 C/C++ 中的 float 、 double,Pascal 中的 real 、 double 、 extended 等)存储获奖比例 w%,则计算 5×60% 时的结果可能为 3.000001,也可能为 2.999999,向下取整后的结果不确定。因此,建议仅使用整型变量,以计算出准确值。

来源

CSP-J

兄弟们啊,不是你们c++学不会,而是个别老师他教不对啊。

来,就这题你看着懵不懵,懵不懵!

看看老高平时是怎么教我的:

要解决这个问题,我们需要逐个处理输入的选手成绩,并在每处理完一个成绩后计算出当前的获奖分数线。具体的步骤如下:

  1. 读取输入的选手总数 n 和获奖百分比 w
  2. 初始化一个空的成绩列表,并逐个读取输入的成绩。
  3. 对每个成绩,计算当前已评出的选手人数 p,然后根据公式 max(1, ⌊p * w%⌋) 计算当前计划获奖人数。
  4. 找到当前成绩列表中排名在该计划获奖人数范围内的最低分数作为获奖分数线。注意,如果有成绩并列,需要考虑所有并列的成绩。
  5. 输出每个成绩后的即时获奖分数线。

下面是实现这个逻辑的 C++ 代码:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    int n, w;
    std::cin >> n >> w;

    std::vector<int> scores;
    std::vector<int> thresholds;

    for (int i = 0; i < n; ++i) {
        int score;
        std::cin >> score;
        scores.push_back(score);

        // Sort the scores to make it easier to find the threshold
        std::sort(scores.begin(), scores.end());

        // Calculate the number of winners so far
        int p = i + 1;
        int num_winners = std::max(1, p * w / 100);

        // The threshold is the num_winners-th score in the sorted list
        int threshold = scores[num_winners - 1];

        // Output the current threshold
        thresholds.push_back(threshold);
    }

    // Output all thresholds
    for (size_t i = 0; i < thresholds.size(); ++i) {
        if (i > 0) std::cout << " ";
        std::cout << thresholds[i];
    }
    std::cout << std::endl;

    return 0;
}

 

解释

  1. ‌输入读取‌:

    • 首先读取 n 和 w
    • 然后逐个读取成绩,并存储在 scores 向量中。
  2. ‌排序和计算获奖分数线‌:

    • 每次添加新成绩后,对 scores 进行排序。
    • 根据当前已评人数 p 计算计划获奖人数 num_winners
    • 获奖分数线即为排序后成绩列表中的第 num_winners - 1 个成绩(因为索引从0开始)。
  3. ‌输出获奖分数线‌:

    • 将每个成绩后的获奖分数线存储在 thresholds 向量中。
    • 最后输出所有存储的获奖分数线,用空格分隔。

注意事项

  • 由于获奖人数是根据百分比计算的,因此要用整数运算来避免浮点数精度问题。
  • 每次都要对成绩列表进行排序,以便找到当前的前 num_winners 个成绩。虽然排序的时间复杂度是 O(plogp),但由于每次只增加一个成绩,这种方法在实际应用中是高效的。

这个代码实现了需求,并可以处理题目中给出的所有测试数据规模。

结束了!

对了,忘说了一句话:

要想c++成绩好,就来jiabei小课堂

还有,点我主页,看我简介,别给那三个人点赞就完了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值