[NOI2015] 荷马史诗 题解
/*
思路,
简化题意, 即构造一颗 k 叉树, 每个节点的
权值为其所有孩子的权值之和, 给定的 n 个
数必须使用, 其余空缺处用 0 补全.
考虑使用优先队列, 首先弹入 n + (n-1) %
(k-1) 个元素 ( 不足处用 0 代替), 然后每
次弹出前 k 小的数并插入其和, 知道优先队
列中只剩余一个元素. 计算时同时保存深度.
由于优先队列默认从大到小排序, 而用 pair
比较方便, 所以处理时我们将队列中的数取
反, 计算结果时再次取相反数.
*/
#include <stdio.h>
#include <iostream>
#include <queue>
#define ll long long
using namespace std;
ll n, k;
priority_queue < pair <ll, ll> > pq;
int main () {
scanf("%lld %lld", &n, &k);
for (int i = 1; i <= n; i++) {
ll x;
scanf("%lld", &x);
pq.push(make_pair(-x, 0));
}
// 插入 0:
while ((n - 1) % (k - 1)) {
pq.push(make_pair(0, 0));
n++;
}
ll ans = 0;
while (pq.size() != 1) {
ll sigma = 0, high = 0;
for (int i = 1; i <= k; i++) {
sigma += pq.top().first;
high = min(high, pq.top().second);
pq.pop();
}
pq.push(make_pair(sigma, high - 1)); // 注意 high 也是一个非正数
ans += sigma;
}
printf("%lld\n%lld\n", -ans, -pq.top().second);
return 0;
}
( ゚∀゚)o彡゜ ヒーコー ヒーコー!

浙公网安备 33010602011771号