POJ2833 The Average(優先隊列/堆排序)

The Average
Time Limit: 6000msMemory Limit: 10000KB 64-bit integer IO format: %lld Java class name: Main
Submit Status
In a speech contest, when a contestant finishes his speech, the judges will then grade his performance. The staff remove the highest grade and the lowest grade and compute the average of the rest as the contestant’s final grade. This is an easy problem because usually there are only several judges.

Let’s consider a generalized form of the problem above. Given n positive integers, remove the greatest n1 ones and the least n2 ones, and compute the average of the rest.

Input
The input consists of several test cases. Each test case consists two lines. The first line contains three integers n1, n2 and n (1 ≤ n1, n2 ≤ 10, n1 + n2 < n ≤ 5,000,000) separate by a single space. The second line contains n positive integers ai (1 ≤ ai ≤ 108 for all i s.t. 1 ≤ i ≤ n) separated by a single space. The last test case is followed by three zeroes.

Output
For each test case, output the average rounded to six digits after decimal point in a separate line.

Sample Input
1 2 5
1 2 3 4 5
4 2 10
2121187 902 485 531 843 582 652 926 220 155
0 0 0
Sample Output
3.500000
562.500000
Hint
This problem has very large input data. scanf and printf are recommended for C++ I/O.

The memory limit might not allow you to store everything in the memory.

分析:
第一眼當然是先排序然後去掉最大的N1個和最小的N2個,算平均值。

時間上nlg2n 。但空間開不下:限制1000k 而開數組 5*10^6*4 大概是2000k。
所以如果能一開始加的時候就只加最大的n1個和最小的n2個就好了=-=
然後發現題目裏n1 n2 都非常小。
如果維護一個最小堆的話,裏面只有n1個數,每加進去第n1+1個數都把最小的那個彈出去,遍歷完之後,裏面剩下的就是最大的n1個數了。

唉,但是我不會寫堆誒= =
很早以前學的因爲用的少早就忘了,目瞪口呆.jpg
怎麼辦呢
原來c++的STL有 優先隊列這種東西。priority_queue
以前聽名字覺得弔弔的,其實就是個堆……?
默認的時候,裏面就是維護了一個最大堆。

基本操作:
empty() 如果優先隊列爲空,則返回真
pop() 刪除第一個元素
push() 加入一個元素
size() 返回優先隊列中擁有的元素的個數
top() 返回優先隊列中有最高優先級的元素

然後就解決啦!!
不過我只看了個皮毛解決當前的問題,貼個地址以後慢慢看:http://blog.sina.com.cn/s/blog_959bf1d3010191h1.html

//  Created by ZYD in 2015.
//  Copyright (c) 2015 ZYD. All rights reserved.
//

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define Size 100000
#define ll long long
#define mk make_pair
#define pb push_back
#define mem(array) memset(array,0,sizeof(array))
typedef pair<int,int> P;
int n1,n2,n;
// int a[5000005];
priority_queue<long long > big,small;
long long sum,a;
int main()
{
    freopen("in.txt","r",stdin);
    while(~scanf("%d %d %d",&n1,&n2,&n)){
        if(n1==0 && n2==0 && n==0) break;
        // memset(a,0,sizeof(a));
        sum=0;
        for(int i=1;i<=n;i++) 
        {
            scanf("%lld",&a);
            sum+=a;
            big.push(-a);
            if(big.size()>n1) big.pop();
            small.push(a);
            if(small.size()>n2) small.pop();
        }       
        for(int i=0;i<n1;i++){
            sum+=big.top();
            big.pop();
        }
        for(int i=0;i<n2;i++){
            sum-=small.top();
            small.pop();
        }
        printf("%.6f\n",(sum*1.0)/(n-n1-n2));
    }
    return 0;
}


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