合并果子裸题
每次选取最小的两个合并即可
证明:
把合并过程画成哈夫曼树,如果最小点的兄弟不是次小点,把次小点和最小点的兄弟换一个位置答案肯定不会更劣。
也就是记次小点i,最小点的兄弟j,点到根的距离为d,点权为w
由
w[i]<w[j],d[i]<d[j]
一定有
d[j]∗w[j]+d[i]∗w[i]>d[j]∗w[i]+d[i]∗w[j]
#include<cstdio>
#include<algorithm>
#define N 20005
#define ll long long
using namespace std;
int heap[N], tot=0;
void heap_add(int x)
{
heap[++tot]=x;
for(int i = tot, j = i>>1; j; i = j, j >>=1)
{
if(heap[j]>heap[i])swap(heap[j],heap[i]);
else break;
}
}
void heap_del()
{
heap[1]=heap[tot--];
for(int i = 1, j = i<<1; j <= tot; i = j, j<<=1)
{
if(heap[j]>heap[j|1] && j<tot)j|=1;
if(heap[j]<heap[i])swap(heap[j],heap[i]);
else break;
}
}
int main()
{
ll ans=0;
int n;
scanf("%d",&n);
for(int i = 1, x; i <= n; i++)
{
scanf("%d",&x);
heap_add(x);
}
for(int i = 1; i < n; i++)
{
ll temp=heap[1];
heap_del();
temp+=heap[1];
heap_del();
ans+=temp;
heap_add(temp);
}
printf("%lld\n",ans);
}