你的眸子里有泉水的声音————空间换时间——桶排序——洛谷P7072

上链接:https://www.luogu.com.cn/problem/P7072

上题干:

题目描述

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

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

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

输入格式

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

输出格式

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

这道题是一个模拟题,那么我们就按照题意来模拟。

我们按照它给的样例来,

n=10,w=60;

当输入第一个人的成绩:200,排下序:200 ,更新一下当前获奖人数:max(1,1*0.6)=1

即时获奖分数线:200

当输入第二个人成绩:300 ,排一下序:300 ,200 更新一下当前获奖人数:max(1,2*0.6)=1

即时获奖分数线:300

当输入第三个人成绩:400 ,排一下序:400,300 ,200 更新一下当前获奖人数:max(1,3*0.6)=1

即时获奖分数线:400

当输入第四个人成绩:500 ,排一下序:500,400,300 ,200 更新一下当前获奖人数:max(1,4*0.6)=2

即时获奖分数线:400

当输入第五个人的成绩:600,排序:600 500 400 300 200  更新一下当前获奖人数:max=(1,5*0.6)=3

即时获奖分数线:400

…………

所以,我们需要的操作就是:1,循环读入第i个人的成绩。2,每次把当前拥有的人的成绩排序,更新获奖人数,根据获奖人数,从最大成绩开始往下扫描获奖人数个单位,这个扫描到的成绩就是即时获奖分数线,我们此时将它输出即可。

但是我们会发现,如果用快排,sort排序,等排序,会超时。

并且,我们的数据有一个特点:就是这个数列的值域很小,【0,600】

所以我们可以用    我们的经典排序————桶排序(计数排序)来达到空间换时间的效果。

我们只需要准备0~600 这么601个桶,用桶的下标来储存成绩,桶装这个成绩的人数。

然后就不需要再特地排序了,因为我们的即时获奖分数线是从最高的分数,往下数(计划获奖人数)个单位。

我们只需要把序号高的桶放在第一位,用sum变量累加从最高分开始的人数,如果这个人数,超过了计划人数,那么此时的分数就是获奖分数线。

上代码:

const int N = 1e5 + 10;
int n, w;
int a[N];
int box[N];
int main()
{
	cin >> n >> w;
	for(int i=1;i<=n;i++)
	{
		cin >> a[i];
		box[a[i]]++;
		int sum = 0;
		for (int j = 600; j >= 0; j--)
		{
			sum += box[j];
			int plan = max(1,(int) (i * w / 100.0));
			if (sum >= plan)
			{
				cout << j<<' ';
				break;
			}
		}
	}
}


	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

louisdlee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值