简单的
小根堆模拟
可以证明每次合并最小的两个果子是这题的最优解
于是这道题目变成重复n-1次做四个操作:
1)取出根x,维护堆
2)取出根y,维护堆
3)ans+=x+y ;
可以证明每次合并最小的两个果子是这题的最优解
于是这道题目变成重复n-1次做四个操作:
1)取出根x,维护堆
2)取出根y,维护堆
3)ans+=x+y ;
4)加入节点(x+y)入堆,维护堆
见代码:
#include<bits/stdc++.h>
using namespace std;
int h[100010],x,y,n,i,a,b,m;
long long ans;
void pushup(int x){
for(;h[x]<h[x>>1]&&x>1;x>>=1)
swap(h[x],h[x>>1]);
}
void pushdown(int x){
for(;x<<1<=n;x=y){
y=x<<1;
if(y<n&&h[y|1]<h[y])y|=1;
if(h[x]>h[y])swap(h[x],h[y]);
else return;
}
}
void del(int x){
swap(h[x],h[n--]);
pushup(x);
pushdown(x);
}
void add(int x){
h[++n]=x;
pushup(n);
}
int main(){
scanf("%d",&m);
for(i=1;i<=m;i++)
scanf("%d",&x),add(x);
for(m--;m--;){
a=h[1];
del(1);
b=h[1];
del(1);
add(a+b);
ans+=a+b;
}
printf("%lld\n",ans);
}