Sicily 1022. Poor contestant Prob

 

Problem
As everybody known, “BG meeting” is very very popular in the ACM training team of ZSU. 
After each online contest, they will go out for “smoking”. Who will be the poor ones that have to BG the others? Of course, the half who solve less problems. 
The rule runs well when the number of the contestants is even. But if the number is odd, it is impossible to divide them into two equal parts. It gives a dilemma to the BG meeting committee. After a careful discussion with Mr. Guo, a new rule emerged: if the number of the contestant is odd, the committee will first sort the contestants according to the number of problems they solved, and then they will pick out the middle one. This poor boy or girl will have no chance to attend the BG meeting. 
Strange rule, isn`t it?
As the number of the contestants is becoming more and more large, the committee need to write a program which will pick out the poor one efficiently.
Note that: Every contestant solves different number of problems. The total number of the contestants will not exceed 10^5.
Input
There are several cases in the input. The first line of the input will be an integer M, the number of the cases.
Each case is consisted of a list of commands. There are 3 types of commands.
1. Add xxx n : add a record to the data base, where xxx is the name of the contestant, which is only consisted of at most 10 letters or digits, n is the number of problems he/she solved. (Each name will appear in Add commands only once).
2.Query :
3.End :End of the case.
Output
1.For the Query command: If the current number of contestants is odd, the program should output the poor contestant’s name currently even if there is only one contestants, otherwise, just out put “No one!” (without quotes).
2.For the End command: 
   If the total number of contestants in the data base is even, you should out put “Happy BG meeting!!”(without quotes),otherwise, you should out put the “xxx is so poor. ”(without quotes) where xxx is the name of the poor one.
3.Each case should be separated by a blank line.
Sample Input
2
Add Magicpig 100
Add Radium 600
Add Kingfkong 300
Add Dynamic 700 
Query
Add Axing 400
Query
Add Inkfish 1000
Add Carp 800
End

Add Radium 100
Add Magicpig 200
End
Sample Output
No one!
Axing
Radium is so poor.

Happy BG meeting!!
这道题乍一看来很简单,但是在打的数据量时,用一般的插入方法肯定会查超时,所以当时的第一反应是用排序二叉树,但是排序二叉树是不稳定的,它的时间复杂度介于O(logn)与O(n)之间,当输入数据是已排好序的数据时,则其时间复杂度就是O(n),这样做在这道题的数据下已经超时了。鉴于这种情况,要用一种稳定的方法,而且时间复杂度要求最多数O(log n),这样的话,很显然堆可以满足要求。
在这道题中,要查询的是中间元素,所以在此利用这个要求就有了个比较适合的数据结构,即,设计两个堆,一个是大根堆,一个是小根堆,且要求小根堆中的任意元素都要大于大根堆中的所有元素,而且大根堆的元素数要大于等于小根堆元素,使得中间元素在总数为奇数的情况下处于大根堆的堆顶,这样的话,对与中间元素的查找复杂度就是O(1)了。这里的唯一复杂度就是堆的调整,而堆的调整的复杂度为O(log n),可以保证题目要求。由于既有从堆顶加入元素又有从堆尾加入元素,所以要设计两个调整函数,一个从堆顶开始向下调整,这个和堆排序中的调整是一样的,另一个就是从堆尾调整,这个是前一个函数的反向,主要注意下表的变换即可。
做这道题的时候先后大改了三次程序,第一次是写成了排序二叉树,第二次堆调整的时候用的是建堆过程,所以前两次均超时,第三次是因为一个对与每一个case少了对nmin和nmax,即大小根堆的计数器进行初始化...而且这第三次话了我很长很长很长很长时间...发现了以后着实很无语...内流满面了...
不过现在Sicily上的用时是0.54s,肯定还有更优化的方法,简单的有,将中间元素单独拿出来记录,然后分别调整两个堆,另一种比较高深..传说中的离散化+树形数组,貌似是将所有元素一一对应到一个数组中,每个元素有独有的地址,根据地址二分查找中间元素...但是还未曾了解具体过程,等了解后再说吧...
附上代码:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值