这道题的关键点在于要看出那条式子是哈夫曼树的表达式
哈夫曼树一般可以用来解决一些最佳判定或者编码之类的问题 比如给学生的成绩分类 原理就是把其中元素出现的概率设为树的边权 代价就是边权乘深度的和 构造一棵哈夫曼树主要是dp和贪心两种做法
贪心就是一般教科书讲得从最小元素入手 dp的话就是反过来 因为大的元素肯定应该在树深度比较低的地方 所以把所有元素从大到小排序 一开始假定有一棵大的树 含有一些空的叶节点 每次是两种转移方法要么把第一个没处理的元素插入空的叶节点中 要么把叶节点扩展 然后剩下没处理的权值深度加一 故代价也要加上一次他们的和
具体参见:点击打开链接
这里已知是哈夫曼树的话 直接用贪心的做法就好了 比较好的做法就是用优先队列:
#include <set>
#include <map>
#include <list>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
priority_queue<ll,vector<ll>,greater<ll> > q;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
while(!q.empty()) q.pop();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
ll x;
scanf("%lld",&x);
q.push(x);
}
ll ans=0;
while(q.size()>1)
{
cout<<q.top()<<endl;
ll tmp=0;
tmp+=q.top();
q.pop();
tmp+=q.top();
q.pop();
ans+=tmp;
q.push(tmp);
}
printf("%lld\n",ans);
}
}