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);
}