4198: [Noi2015]荷马史诗
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1512 Solved: 797
[Submit][Status][Discuss]
Description
追逐影子的人,自己就是影子。 ——荷马
Input
输入文件的第 1 行包含 2 个正整数 n,k,中间用单个空格隔开,表示共有 n 种单词,需要使用 k 进制字符串进行替换。
Output
输出文件包括 2 行。
Sample Input
1
1
2
2
Sample Output
2
HINT
Source
学习了一发哈夫曼树... 于是就来看这道当时让很多神犇跪倒的题目... 怎么会考到这么偏的东西? 不会就跪啊. 看了之后再来看这道题? ??? k进制所以是k叉哈夫曼? 长度最小同时最长也要最小只要在建树过程中贪心一下就行了. 权值相同要深度最小的. 注意不满k叉要补0点.
为什么priority_queue的排序重载方式要反过来? 调了半天. (主要是我弱)
#include<bits/stdc++.h>
using namespace std;
typedef long long lnt;
lnt ans;
int n, res, k;
struct node {
lnt val; int dep;
inline friend bool operator < (const node &a ,const node &b) {
return (a.val == b.val) ? a.dep > b.dep : a.val > b.val;
}
};
priority_queue<node> q;
inline const lnt read() {
register lnt x = 0;
register char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
int main() {
n = read(), k = read();
register lnt x;
register int i, res;
for (i = 1; i <= n; ++ i)
x = read(), q.push((node){x, 1});
res = (n - 1) % (k - 1);
if (res) res = k - 1 - res, n += res;
for (i = 1; i <= res; ++ i) q.push((node){0, 1});
while (n > 1) {
int mxd = 0;
lnt mxv = 0;
for (i = 1; i <= k; ++ i) {
mxv += q.top().val;
mxd = max(mxd, q.top().dep);
q.pop();
}
n -= k - 1;
ans += mxv;
q.push((node){mxv, mxd + 1});
}
printf("%lld\n%d", ans, q.top().dep - 1);
}