★USACO 2017 Dec. Silver★
-比赛回顾
A-Homework
◆一些有趣的事◆
虽然这个比赛已经过去很久了,我们的老师还是不辞辛劳地找出来,把它作为新一轮的考试题目。考试前,老师笑呵呵地对我们说:“让你们看一看什么是难得要命的模拟题”。于是我也笑呵呵地炸了…
◆题目◆
◆大致翻译◆
题目:牛吃了我的作业
在你的历史课上,你得到了一个很长的作业。这个作业包含了N个题目(3 ≤ N ≤ 100,000),每个题目的成绩在0~10,000之间。
按照惯例,你的老师按照以下方式计算最终成绩:去掉你最低的一个成绩,然后将其余成绩的平均成绩作为最终成绩。但不幸的是,你的宠物牛“贝西”刚刚吃了前K个题目的答案!(1 ≤ K ≤ N-2)
经过你的一番解释,老师终于相信了你的故事,并且同意对你有答案的题目(没有被吃掉答案的题目)像之前一样给分——通过去掉最低的成绩(如果有多个最低成绩,则只去掉其中一个)并取剩余成绩的平均成绩。
根据这一成绩计算方案,请按升序输出所有可以使你最终成绩最高的K的值。
(copy from LuoGu)
◆解析◆
我必须承认——在看到数据规模的一瞬间,我想到了二分查找…
但是似乎并没有什么可以二分的东西(没有规律),所以……按照往年的套路,第一道题大概是枚举。
1)枚举
套路再一次拯救了我的成绩——一般来说,第一道题就是让你枚举答案。所以枚举K从 1 ~ N-2 (题目是这么说的)。
2)查找最小值
由于这道题的数据规模庞大,所以大概是要维护一个优先队列。即维护一个存储最小值的小根堆,堆顶元素即是最小值。但是由于我们一直在删除前面的元素,堆顶元素可能已经被删除了,所以必须要对堆顶进行维护。我们需要判断当前的堆顶元素的位置是否在已经删除的部分,如果是,就pop() (因为是按顺序枚举,所以pop了就可以不管这个元素了)。这样的话就需要用结构体为变量类型定义 priority_queue<Que>
了,Que如下
struct QUE
{
int num,where; //数字,位置
}Push;
3)求平均值
首先需要实现的是删除前K个元素后的和——不难想到用一个变量 sum 存储当前删除前K个元素后的和。每一次删除后的和相当于上一次删除后的和减去第K个元素即当前删除的元素的值。最后减去最小值,除以当前元素的个数即得到平均值,记得用 double 存储。
4)别急着交题
有一些坑点:
1. 这玩意如果有多个满足最大值的K,需要从小到大依次输出所有满足的K(我没看到这个于是Wa了);
2. double误差……这个老梗,只需要将你所得的平均值乘上1e5(提高精度)然后取整就可以啦;
◆代码◆
这是我自己写的,可能方法与其他的不太一样…
下面附上Gitee(码云)地址:
★USACO 2017 December Contest, Sliver★ Homework