Sicily 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

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;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章