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
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!!
Problem Source
ZSUACM Team Member
Solution
题目的意思是不断取出中间那个数,一开始很容易想到的就是暴力排序,但是看到了数据规模是100000,就算是快排也是会超时的,因为是中间的那一个数,所以很容易想到就是维护左边序列和右边序列。而左边序列要有最大值供插入时参考,右边序列要有最小值供插入值参考。
于是就想到了最大堆和最小堆。
在STL中有对堆的函数支持:
他们的头文件函数是#include <algorithm>
首先是make_heap(); // void make_heap(first_pointer,end_pointer,compare_function);
一个参数是数组或向量的头指针,第二个向量是尾指针(对于数组来说是最后一个元素的下一个位置)。第三个参数是比较函数。在缺省的时候,默认是大跟堆。
作用:把这一段的数组或向量做成一个堆的结构。范围是[first,last)
然后是pop_heap(); // void pop_heap(first_pointer,end_pointer,compare_function);
作用:pop_heap()不是真的把最大(最小)的元素从堆中弹出来。而是重新排序堆。它把first和last交换,然后将[first,last-1)的数据再做成一个堆。
接着是push_heap(); // void pushheap(first_pointer,end_pointer,compare_function);
作用:push_heap()假设由[first,last-1)是一个有效的堆,然后,再把堆中的新元素加进来,做成一个堆。
最后是sort_heap(); // void sort_heap(first_pointer,end_pointer,compare_function);
作用是sort_heap对[first,last)中的序列进行排序。它假设这个序列是有效堆。(当然,经过排序之后就不是一个有效堆了)
所以堆排序可以先调用make_heap(),然后就是sort_heap();
整体思路就是左边序列用大根堆来保存,右边序列用小根堆来保存,注意cmp的书写的时候,不和sort的函数参数是返回true的时候不调整,堆的函数参数是满足时进行调整,容易写错。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char name[100005][15];
int slove[100005], max_l[100005], min_l[100005];
bool max_cmp(const int a, const int b) {return slove[a] < slove[b];} //大根堆
bool min_cmp(const int a, const int b) {return slove[a] > slove[b];} //小根堆
int main()
{
int t, c = 0;
scanf("%d", &t);
while (t--)
{
if (!c) c = 1;
else printf("\n");
int i, j, k, n;
char temp[6];
memset(name, 0, sizeof(name));
memset(slove, 0, sizeof(slove));
i = j = k = 0;
while (scanf("%s", temp) != EOF && temp[0] != 'E')
{
if (temp[0] == 'A')
{
scanf("%s%d", name[k], &slove[k]);
if (i <= j && i > 0 && slove[k] < slove[max_l[0]])//注意保持两个堆的平衡,我是优先填入小根堆,并且填入时注意需要交换的特殊情况
{
pop_heap(max_l, max_l+j, max_cmp);//取出
min_l[i] = k;
swap(min_l[i], max_l[j-1]);//交换
++i;
push_heap(min_l, min_l+i, min_cmp);//调整
push_heap(max_l, max_l+j, max_cmp);
}
else if (i <= j)
{
min_l[i] = k;
++i;
push_heap(min_l, min_l+i, min_cmp);
}
else if (i > j && slove[k] > slove[min_l[0]])//需要填入大根堆,但是需要和小根堆的最小交换的特殊情况
{
pop_heap(min_l, min_l+i, min_cmp);
max_l[j] = k;
swap(max_l[j], min_l[i-1]);
++j;
push_heap(min_l, min_l+i, min_cmp);
push_heap(max_l, max_l+j, max_cmp);
}
else
{
max_l[j] = k;
++j;
push_heap(max_l, max_l+j, max_cmp);
}
++k;
}
else if (temp[0] == 'Q')
{
if (i == j) printf("No one!\n");
else
{
printf("%s\n", name[min_l[0]]);
}
}
}
if (i == j) printf("Happy BG meeting!!\n");
else
{
printf("%s is so poor.\n", name[min_l[0]]);
}
}
return 0;
}