/*
本题是一个比较简单的堆排序的题目,
思想和之前的合并果子非常像(简直一模一样) 我每次找到数列中最小的俩个进行合并,
再将合并后的数存入数列中 (可以用堆实现,大佬可以无视直接用优先队列,原理是一样的,
我们建立一个二叉树,让每个子节点都大于它的父亲节点 二叉树的根节点就成了最小值)
再找新的数列中最小的俩个;
(以此类推,并将过程中找到的合并后的值加起来就是答案)
*/
#include<bits/stdc++.h>
using namespace std;
int n;
long long l,s[50000],da;//题目数字给的太大了,不开long long过不了。
void sf(int wz)//上浮,将一个新值按规矩上移(每个子节点都大于它的父亲节点)
{
while(wz!=1)//到顶结束
int cnm=wz>>1;//位运算,相当于除以2(向下取);
if(s[wz]<s[cnm])
swap(s[wz],s[cnm]);
else//找到自己位置也可以结束
break;
wz=cnm;
}
void xc()//下沉,将一个较大值按规矩下移(顺便找到新的最小)
int wz=1;
while((wz<<1)<=n)
int cnm=wz<<1;//相当于乘2
int t=wz;//t表示我当前的值和t的值交换
if(cnm<=n&&s[wz]>s[cnm])
t=cnm;//有左边并且可换
if(s[wz]>s[cnm+1]&&s[cnm]>s[cnm+1]&&cnm+1<=n)
t=cnm+1;//有右边并且比左边好
if(t!=wz)//不等交换
swap(s[wz],s[t]);
else//找到位置,不动了
·break;
wz=t;
int main()
cin>>n;
for(int i=1;i<=n;i++)
cin>>l;
s[i]=l;//表示我新进来一个数,我先暂时把它放在完全二叉树末尾(也就是第i个)
sf(i);//我要把树中第i个点的数按要求上浮(上小下大)
for(int i=1;n!=1;i++)//当我节点个数为1时就做完了
int k=s[1];//取一个最小
s[1]=s[n--];//将这个最小变为一个较大值
xc();//把这个较大值下沉(相当于去掉最小,重新找最小)
k=k+s[1];//再取
s[1]=s[n--];//再删
xc();
s[++n]=k;//将新值存入完全二叉树末尾
sf(n);//再次上浮
da=da+k;//累计答案
cout<<da;