题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=1280
题目思想:这题快排可以A,鉴于在学习堆排,就试试了,看人家代码过的,深刻理解了堆吧,
堆:
建堆,insert,插在完全树尾n位置,同时需要up,往上比较;
出堆,pop,输出root,并且把root和最后树尾交换,同时需要,down往下比较。
#include<iostream>
#include<cstdio>
using namespace std;
int a[3000+3],b[3000*2999/2+3];
int t;
void swap(int i,int j){
int temp;
temp=b[i] ; b[i]=b[j]; b[j]=temp;
}
void up(int c)
{
int k=c/2;
if(c==1)return;
if(b[k]<b[c]){
swap(k,c);
up(k);
}
}
void insert(int x)
{
b[++t]=x;
up(t);//不管是左节点还是右节点,都是/2,头节点的下标是从1开始的
}
void down(int c)
{
int k=2*c;
if(k>t)return;
if(k+1<t)
//k<=t的情况下,判断右节点是否存在
k = b[k]>b[k+1]?k:(k+1);
if(b[k]>b[c]){
swap(k,c);
down(k);
}
}
int pop()
{
int x = b[1];
swap(1,t--);
down(1);
return x;
}
int main()
{
int i,j,n,m;
while(~scanf("%d%d",&n,&m))
{
t=0;
for(i=0;i<n;i++)scanf("%d",&a[i]);
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
insert(a[i]+a[j]);
for(i=0;i<m;i++)
printf(i==0?"%d":" %d",pop( ));//
printf("\n");
}
return 0;
}