題目
話說3008年的Orz教主節,全民狂歡,傳遞教主聖火,以致萬人空巷,股票飛漲。真乃鑼鼓喧天,鞭炮齊鳴,紅旗招展,人山人海吶。可是小X爲了準備NOIP3008,不得不待在家裏好好Coding。小X希望早點結束當天的任務,加入聖火傳遞隊伍中去。
在這個不亞於狂歡節的日子裏,小X的老師卻“公然違抗”休假法令,佈置小X寫一個小根堆,但是小X不會堆的操作,所以想了一個偷懶的辦法:
堆是一棵完全二叉樹,每個結點有一個權。小根堆的根的權最小,且根的兩個子樹也是一個堆。可以用一個數組a來記錄一棵完全二叉樹,a[1]爲根結點,若結點a[j]不是根結點,那麼它的父親爲a[j/2](取下整);若結點a[k]不是葉子結點,那麼它的左兒子爲a[2k],它的右兒子爲a[2k+1]。
他希望一組數據按一定順序依次插入數組中(即第i個數爲a[i]),最後得出來就已經是一個堆,即不需要任何交換操作,若有多種方法,輸出字典序最大的一組,顯得這個數據更亂。
解題思路
對於當前序列,我們肯定是選最小的放在堆頂。
然後分左右子樹(大的分左邊,小的分右邊),顯然可以重複現在的選擇。
代碼
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[70000],m,b[70000];
void fz(int l,int r,int k){
b[k]=a[l];
if (l==r) return;
int mid=(l+r)>>1;
fz(mid+1,r,2*k);
fz(l+1,mid,2*k+1);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
fz(1,n,1);
for(int i=1;i<n;i++) printf("%d ",b[i]); printf("%d\n",b[n]);
}