题目
思路
首先,很容易得到,它一定是一棵完全二叉树。
所以,非叶子节点延伸出去的点一定是成对的(废话)
把每张扑克看做一个子树,现在我们要把它们合并。
由于是完全二叉树,且需要分数最小,所以每次合并两棵最小的子树。
是不是有点熟悉?
没错,这就是合并果子!
建一个堆即可解决。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f,maxn=1e4+777;
int c[maxn*2],n,ass=0,cnt=0;
void up(int x)
{
int i=x;
while(i/2>0)
{
if(c[i]<c[i/2]) swap(c[i],c[i/2]);else break;
i>>=1;
}
}
void down(int x)
{
int i=x;
while(i*2<=cnt)
{
int t=i*2;
if(t+1<=cnt&&c[t]>c[t+1]) t++;
if(c[i]>c[t]) swap(c[i],c[t]);else break;
i=t;
}
}
void ins(int x)
{
c[++cnt]=x;
up(cnt);
}
void del()
{
swap(c[1],c[cnt]);
cnt--;
down(1);
}
int pop()
{
int x=c[1]; del();
return x;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&x);
ins(x);
}
while(cnt>1)
{
int x1=pop(),x2=pop();
ass+=x1+x2;
ins(x1+x2);
}
printf("%d",ass);
}