算法
(贪心,哈夫曼树,堆,优先队列) O(nlogn)
经典哈夫曼树的模型,每次合并重量最小的两堆果子即可。
时间复杂度
使用小根堆维护所有果子,每次弹出堆顶的两堆果子,并将其合并,合并之后将两堆重量之和再次插入小根堆中。
每次操作会将果子的堆数减一,一共操作 n−1 次即可将所有果子合并成1堆。每次操作涉及到2次堆的删除操作和1次堆的插入操作,计算量是 O(logn)。因此总时间复杂度是 O(nlogn)。
C++ 代码
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
priority_queue<int, vector<int>, greater<int>> heap;
while (n -- )
{
int x;
scanf("%d", &x);
heap.push(x);
}
int res = 0;
while (heap.size() > 1)
{
int a = heap.top(); heap.pop();
int b = heap.top(); heap.pop();
res += a + b;
heap.push(a + b);
}
printf("%d\n", res);
return 0;
}
我还没听讲解,竟然和y总写的一模一样,好开心
👍
牛啊牛啊
这里有物资!
wocao
最简单的一集
直接用优先队列的话能不能过呢
可以的,直接取负就可以了。
#include <iostream> #include <queue> using namespace std; int main() { int n; cin >> n; priority_queue<int> heap; while(n--) { int x; cin >> x; heap.push(-x); } int ans = 0; while(heap.size() > 1) { int a = heap.top(); heap.pop(); int b = heap.top(); heap.pop(); ans -= a + b; heap.push(a + b); } cout << ans << endl; }
请问,为什么要取负值?
这样的话,按绝对值来看,优先队列里果子的重量就是从小到大排序了。
默认是大根堆
小根堆巧妙地解决了熵的不确定性,每次都实现了最小求和的状态,无敌的思路!!
nb
Orz
o(nlogn)
代码需要处理一下边界, 当heap只有一个数的时候, res= heap.top。
题目要求了,n>1
只有一堆就不用合并了,res直接就是0
明明有等号
哈哈哈,我当时看的是>1😂
可能27天之前我看错了hhh
有没有可能只有一堆不需要费力气了,所以是0
hh
哈哈
## 以前是禁止用STL的。如果不用STL呢?
那就自己实现一个堆呗
你给人家难住了
把之前手写堆的代码搬过来
实现堆不算太难