bzoj4198 荷马史诗
关于Huffman树:
大概就是那样子吧。
是这样的:对于最多只能有k个叉的树,我们想要使得∑val(i) * deep(i)最大
那么我们补0后建立小根堆即可。
最典型例题:合并果子。
然后是这个:
1 /************************************************************** 2 Problem: 4198 3 Language: C++ 4 Result: Accepted 5 Time:1032 ms 6 Memory:3896 kb 7 ****************************************************************/ 8 9 #include <cstdio> 10 #include <queue> 11 const int N = 100010; 12 typedef long long LL; 13 inline void max(LL &a, LL b) { 14 if(a < b) a = b; 15 return; 16 } 17 struct Node { 18 LL val, p; 19 bool operator < (const Node &x) const { 20 if(val != x.val) { 21 return val > x.val; 22 } 23 return p > x.p; 24 } 25 }; 26 27 std::priority_queue<Node> Q; 28 29 Node mk(LL v, LL p) { 30 Node ans; 31 ans.val = v; 32 ans.p = p; 33 return ans; 34 } 35 36 int main() { 37 LL n, k, v; 38 scanf("%lld%lld", &n, &k); 39 for(int i = 1; i <= n; i++) { 40 scanf("%lld", &v); 41 Q.push(mk(v, 0)); 42 } 43 while((n - 1) % (k - 1) != 0) { 44 Q.push(mk(0, 0)); 45 n++; 46 } 47 48 LL ans = 0; 49 50 for(int i = 1; i <= (n - 1); i += (k - 1)) { 51 LL p = 0; 52 v = 0; 53 for(int j = 1; j <= k; j++) { 54 Node nd = Q.top(); 55 Q.pop(); 56 max(p, nd.p); 57 v += nd.val; 58 } 59 ans += v; 60 Q.push(mk(v, p + 1)); 61 } 62 LL p = Q.top().p; 63 printf("%lld %lld", ans, p); 64 return 0; 65 }
之前写的太菜了......
对于这种要让叶权值 * 深度最小的最多k叉树,通解就是每层放k - 1个,然后多的一个向下延伸。
从下往上着构造,要添加0补全。
然后,可以用蚯蚓的套路优化常数(有排序的复杂度)。
如果给定的是有序的或者能够桶排,就能做到O(n + k)。
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 5 typedef long long LL; 6 const int N = 100050; 7 8 struct Node { 9 LL val, deep; 10 inline bool operator <(const Node &w) const { 11 if(val == w.val) { 12 return deep < w.deep; 13 } 14 return val < w.val; 15 } 16 Node(LL a = 0, LL b = 0) { 17 val = a; 18 deep = b; 19 } 20 }a[N]; int top, head = 1; 21 22 std::queue<Node> Q; 23 24 inline Node getmin() { 25 if(Q.empty()) { 26 return a[head++]; 27 } 28 if(head > top || Q.front() < a[head]) { 29 Node t = Q.front(); 30 Q.pop(); 31 return t; 32 } 33 return a[head++]; 34 } 35 36 int main() { 37 LL n, k; 38 scanf("%lld%lld", &n, &k); 39 for(int i = 1; i <= n; i++) { 40 scanf("%lld", &a[i].val); 41 a[i].deep = 1; 42 } 43 44 while((n - 1) % (k - 1)) { 45 n++; 46 a[n].deep = 1; 47 } 48 std::sort(a + 1, a + n + 1); 49 LL ans = 0, d = 0, lm = (n - 1) / (k - 1); 50 top = n; 51 for(int i = 1; i <= lm; i++) { 52 Node s; 53 for(int j = 1; j <= k; j++) { 54 Node t = getmin(); 55 s.val += t.val; 56 s.deep = std::max(s.deep, t.deep); 57 } 58 s.deep++; 59 Q.push(s); 60 ans += s.val; 61 d = std::max(d, s.deep); 62 } 63 64 printf("%lld\n%lld\n", ans, d - 1); 65 return 0; 66 }