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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值