題目大意:
一個小朋友從樹上打下了幾堆果子。要將所有果子合併成一堆。給出沒堆果子的重量求最小力氣
本題的思路是要將重量最小的先合併,也就是傳說中的哈夫曼樹!但本題的數據比較大。今天我們來看堆得寫法:
# include<stdio.h>
# include<stdlib.h>
long long a[1000010];
int main(){
long long sum=0,ans=0,n,i,h,r,j;//本題要用long long不然會答案錯誤
scanf("%I64d",&n);
for(i=1;i<=n;i++){
scanf("%I64d",&a[i]);//將重量存入堆
r=i;//上浮
while(r>1&&a[r]<a[r/2]){
h=a[r];
a[r]=a[r/2];
a[r/2]=h;
r/=2;
}
}
int len=n;
for(i=1;i<n;i++){
sum=a[1];//將當前最小的放到本次合併中
a[1]=a[len];
len--;
r=1;//下沉
while((r*2<=len&&a[r]>a[r*2])||(r*2+1<=len&&a[r]>a[r*2+1])){
j=r*2;
if(j+1<=len&&a[j]>a[j+1])j++;
h=a[r];
a[r]=a[j];
a[j]=h;
r=j;
}
sum+=a[1];//將第二小的加入本次合併中
a[1]=a[len];
len--;
r=1;//下沉
while((r*2<=len&&a[r]>a[r*2])||(r*2+1<=len&&a[r]>a[r*2+1])){
j=r*2;
if(j+1<=len&&a[j]>a[j+1])j++;
h=a[r];
a[r]=a[j];
a[j]=h;
r=j;
}
ans+=sum;//合併
a[++len]=sum;
r=len;//上浮
while(r>1&&a[r]<a[r/2]){
h=a[r];
a[r]=a[r/2];
a[r/2]=h;
r/=2;
}
}
printf("%I64d\n",ans);
}