SOJ 1022

来源:互联网 发布:js pdf 插件 编辑:程序博客网 时间:2024/06/06 00:04

1022. Poor contestant Prob

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

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

2Add Magicpig 100Add Radium 600Add Kingfkong 300Add Dynamic 700 QueryAdd Axing 400QueryAdd Inkfish 1000Add Carp 800EndAdd Radium 100Add Magicpig 200End

Sample Output

No one!AxingRadium is so poor.Happy BG meeting!!

Problem Source

ZSUACM Team Member


  题意就是要找出解题数处于中间的那个人(若总人数为奇数的话),很容易想到将所有人的解题数进行排序然后就能找到处于中间的那个人,但是快排的复杂度是nlogn,面对十万个数据也是会超时的。但要注意到题目只需要找出解题数处于中间的那个人,未必要对所有的数据进行排序。可以用堆或者优先队列来解决这个问题,堆和优先队列的插入删除操作的复杂度都为logn。

  以优先队列为例,确定两个优先队列,一个解题数越大优先级越高Maxque,另一个解题数越少优先级越高Minque,然后将数据按情况插入这两个优先队列中的一个,然后再注意维护两个优先队列的平衡,即保持两个优先队列中元素之差始终小于2,并保持Maxque中的任意数据都小于Minque中的任意数据。最后若总人数为奇数的话,中间的那个人则必定为Maxque的顶部或者Minque的顶部,具体取决于Maxque和Minque的size大小。

  还有尤其要注意的一点是题中用char数组来保存人名和输入的关键词是可行的,但换成string来保存会超时,可见在频繁进行写入时大小固定的char数组效率更高。

#include<iostream>#include<algorithm>#include<queue>#include<cstdio>#include<cstring>using namespace std;struct person{//person类型,数据成员有人的名字以及解题数 char name[10];//切记用char数组来保存字符串,string会超时 int solved;}; class maxCmp{//比较类型,用于priority_queue的构造函数的第三个参量,此类用于最大优先队列,即顶部返回的是解题数最多的人     public:bool operator()(const person &A,const person &B){return A.solved<B.solved;}};class minCmp{//最小优先队列,顶部返回的是解题数最少的人 public:bool operator()(const person &A,const person &B){return A.solved>B.solved;}};priority_queue<person,vector<person>, maxCmp> Maxque;//最大优先队列 priority_queue<person,vector<person>, minCmp> Minque;//最小优先队列 int M;//case数 char s1[6];//用来存储输入的关键字"Add" "Query" "End" int main(){cin>>M;for(int i=0;i<M;++i){while(!Maxque.empty())//清空最大优先队列     {    Maxque.pop();    }    while(!Minque.empty())//清空最小优先队列     {    Minque.pop();    }while(1){scanf("%s",s1);    if(strcmp(s1,"Add")==0){person per;scanf("%s%d",per.name,&per.solved);if(Maxque.empty()||per.solved<Maxque.top().solved) //先向Maxque中添加数据,并且之后解题数小于Maxque中最大值的也向其中添加 {Maxque.push(per);} else//解题数大于Maxque中最大值的则加入Minque,这样就保证了Minque中的任意数据都大于Maxque中的任意数据 {    Minque.push(per);}    if(Maxque.size()>Minque.size()+1)//上面添加数据时未注意平衡的调整,但由于一次添加一个数据,且每次添加完都会验证一次平衡,所以需要调整时两者元素个数之差只会等于2 {Minque.push(Maxque.top());//Maxque个数比Minque多2个,所以将Maxque的top,即最大的数据加入Minque,并在Maxque中将其删除,这样保持了Minque始终大于Maxque Maxque.pop();}else if(Minque.size()>Maxque.size()+1){Maxque.push(Minque.top());//Minque比Maxque多2个,操作类似 Minque.pop();}}else if(strcmp(s1,"Query")==0){if((Maxque.size()+Minque.size())%2==0) cout<<"No one!"<<endl;//两个优先队列的元素总数相加为偶数,则不必寻找排序中间的人 else if(Maxque.size()>Minque.size()) printf("%s\n",Maxque.top().name);//若为奇数,则中间人必为Maxque的top或者Minque的top,这取决于两个优先队列的大小 else printf("%s\n",Minque.top().name);}else {if((Maxque.size()+Minque.size())%2==0) cout<<"Happy BG meeting!!"<<endl;//与Query的情况类似 else if(Maxque.size()>Minque.size()) printf("%s is so poor.\n",Maxque.top().name);else printf("%s is so poor.\n",Minque.top().name);break;}}if(i<M-1) cout<<endl;}return 0;}

0 0
原创粉丝点击