[哈夫曼树][堆]JZOJ 4210 我才不是萝莉控呢qaq
分析
本题今日份好题(我就是一个loli控~qwq)
哈夫曼树有非常简单的实现方法,但是这里运用了一种非常SD的实现方法:DP
因为数组是有序的,所以在哈夫曼树中的深度一定是单调不减的。我们考虑每一个位置, 把 fi,j 看成现在已经放入了下标比 i 小的所有节点,剩余的叶子节点有 j 个。那么我们每一次 有两种选择,第一种是把所有叶子节点都扩展出两个后继,这时剩下所有节点的深度都增加了 1,所以付出的代价是 ∑n k=i+1 Ak,状态变成了 f2i,j;第二种是把第 i 个数填在一个叶子上,这 时状态变成了 fi+1,j−1。最终的答案就是 min fn+1,k(k > 0)。 我们把这个 DP 过程倒过来,就变成了题目中描述的走路的样子。
我比较菜,解释不清,题解from jiry_2
那么我们就知道这是求以A为权值的哈夫曼树的权值和,没了
#include <iostream> #include <cstdio> #include <queue> using namespace std; typedef long long ll; const int N=1e3+10; const ll Inf=1ll<<62; int T,n; priority_queue<ll,vector<ll>,greater<ll> >q; ll ans; int main() { for (scanf("%d",&T);T;T--) { scanf("%d",&n); ll a;ans=0; for (int i=1;i<=n;i++) scanf("%lld",&a),q.push(a); while (q.size()>1) { ll mx=q.top(),mx2; q.pop();mx2=q.top(); q.pop();q.push(mx+mx2); ans+=mx+mx2; } q.pop(); printf("%lld\n",ans); } }
在日渐沉没的世界里,我发现了你。