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 }
AC代码

之前写的太菜了......

对于这种要让叶权值 * 深度最小的最多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 }
新版AC代码

 

posted @ 2018-05-26 17:42  garage  阅读(137)  评论(0编辑  收藏  举报