poj-2388 堆排序

这题想说的太多了,实在太多了,不过,还是先说一下题意吧。

题意就是,输入n个数,去掉n1个最大值,n2个最小值((1 ≤ n1, n2 ≤ 10,n1 + n2 < n ≤ 5,000,000)),求平均数,其中1 ≤ai ≤ 108 for all i s.t. 1 ≤ in.。嗯,题意大概就是这个

然后!重点来了,重点就是题后面的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;
}

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值