这题想说的太多了,实在太多了,不过,还是先说一下题意吧。
题意就是,输入n个数,去掉n1个最大值,n2个最小值((1 ≤ n1, n2 ≤ 10,n1 + n2 < n ≤ 5,000,000)),求平均数,其中1 ≤ai ≤ 108 for all i s.t. 1 ≤ i ≤ n.。嗯,题意大概就是这个
然后!重点来了,重点就是题后面的Hint(提示),提示有两点,一个是数据量很大,不可能全部存下来;第二是数据很大,C++要用scanf和printf来输入输出。更重要的是,我都没管= =,然后没看Hint的我眼泪掉下来。先上来把所有的存下来了,然后排序之后算,发现,果然WA,嗯,这也是不出我所料的,于是果断改成堆排序。
解题具体思想是,由于n1,n2的值都很小,所以建立两个堆:大顶堆呢用来存最小值,也就是最上面的那个是最小值中的最大,只要让输入的数和它比较如果比第一个还大,就不用加入这个大顶堆,如果比这个小呢,就直接覆盖掉这个最大的最小值,然后再生成堆。小顶堆存最大值同理。这样就把存储直接压缩到很小的数量级了。
然后我就照着这个写了,然后发现了一个好东西,就是STL中algorithm头文件中的make_heap函数,这个函数就是用来建立一个堆的,具体的还有好多,后面贴网址,自己看。
然后……我就写完了,我就开始提交,我提交一遍Time Limit Exceeded,我看看,可能是循环或者判断太多了吧,改了结构,把判断改成了一个,不得不说这次修改程序真的变好看了,但是,POJ不是因为帅就能交对的T.T,仍旧Time Limit Exceeded,我照着标准答案,改了10+次,依旧是TM的Time Limit Exceeded。然后,我就开始怀疑,是不是scanf和printf的原因。好了,不说了,我要去把所有WA程序的输入输出都改成scanf,printf了,再见(T_T)~.
噢,对了,这次还发现POJ能看自己的和别人的代码,有时候可能会挺有用。
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
int cmp(int a,int b) {
return a>b;
}
int main() {
long int n;
int n1,n2;
scanf("%d%d%ld",&n1,&n2,&n);
while(1) {
long int minheap[14],maxheap[14];
fill(minheap,minheap+14,0);
fill(maxheap,maxheap+14,100000001);
long long sum=0;
if(n1==0 && n2==0 && n==0) break;
int max_len=0,min_len=0;
bool flag1=0,flag2=0;
for(int i=0; i<n; i++) {
int temp;
scanf("%d",&temp);
if(temp<maxheap[0]){
maxheap[0]=temp;
make_heap(maxheap,maxheap+n2);
}
if(temp>minheap[0]){
minheap[0]=temp;
make_heap(minheap,minheap+n1,cmp);
}
sum+=temp;
}
for(int i=0; i<n1; i++)
sum-=minheap[i];
for(int i=0; i<n2; i++)
sum-=maxheap[i];
printf("%.6lf\n", 1.0*sum/(n-n1-n2));
scanf("%d%d%ld",&n1,&n2,&n);
}
return 0;
}