POJ 2833 The Average(优先队列)
原题目网址:http://poj.org/problem?id=2833
本题中文翻译:
描述
在演讲比赛中,当选手完成演讲时,评委将对他的演出进行评分。 工作人员删除最高成绩和最低成绩,并计算其余成绩的平均值作为参赛者的最终成绩。 这是一个简单的问题,因为通常只有几名评委。
让我们考虑一下上面问题的一般形式。 给定n个正整数,删除最大的n1和最小的n2,并计算其余的平均值。
输入
输入由几个测试用例组成。 每个测试用例由两行组成。 第一行包含三个整数n1,n2和n(1≤n1,n2≤10,n1 + n2 <n≤5,000,000)由一个空格隔开。 第二行包含n个正整数ai(对于所有ai, 1≤i≤n,1≤ai≤10^8)由一个空格隔开。 最后一个测试用例后面跟着三个零。
输出
对于每个测试用例,输出小数点后的平均值,并将其四舍五入为六位数字。
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.(不要用cin或cout)
The memory limit might not allow you to store everything in the memory.
(本题无法让你一次性输入整个序列,空间不允许)
解题思路:
先输入n1+n2个数,将这些数排序,分别将最小的n2个放到大根堆里,将最大的n1个放到小根堆里。
每读入一个元素,如果当前元素比大根堆堆顶小,说明堆顶一定参与计算,则将堆顶弹出,将当前元素推进去;如果当前元素比小根堆堆顶大,说明堆顶一定参与计算,则将堆顶弹出,将当前元素推进去;(感性理解一下)
如果不符合上面两项条件,则说明当前元素一定参与计算。
AC代码:
1 #include<cstdio>
2 #include<queue>
3 #include<algorithm>
4
5 using namespace std;
6
7 priority_queue<int > a;//大根堆
8 priority_queue<int ,vector<int> ,greater<int> > a1;//小根堆
9 int n,n1,n2,k,ll[21];
10 long long ans;
11 double ans1;
12
13 int main() {
14 while(scanf("%d%d%d", &n1, &n2, &n) == 3 && n1 && n2 && n) {
15 while (!a.empty()) a.pop();//初始化一定要记得
16 while (!a1.empty()) a1.pop();//初始化一定要记得
17 ans = ans1 = 0;//初始化一定要记得
18 for(int i = 1;i <= n1 + n2; i++)
19 scanf("%d",&ll[i]);
20 sort(ll+1,ll+n1+n2+1);
21 for(int i = 1;i <= n2; i++)
22 a.push(ll[i]);
23 for(int i = n2 + 1;i <= n2 + n1; i++)
24 a1.push(ll[i]);
25 for(int i = n1+n2+1;i <= n; i++) {
26 scanf("%d",&k);
27 if(k >= a1.top()) {
28 ans += a1.top();
29 a1.pop();
30 a1.push(k);
31 continue;
32 }
33 if(k <= a.top()) {
34 ans += a.top();
35 a.pop();
36 a.push(k);
37 continue;
38 }
39 ans += k;
40 }
41 ans1 = ans;
42 printf("%.6f\n",ans1 / (n - n1 -n2));
43 }
44 return 0;
45 }