bzoj4198 荷馬史詩

關於Huffman樹:ide

大概就是那樣子吧。優化

是這樣的:對於最多隻能有k個叉的樹,咱們想要使得∑val(i) * deep(i)最大spa

那麼咱們補0後創建小根堆便可。code

最典型例題:合併果子。blog

而後是這個:排序

 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代碼

以前寫的太菜了......get

對於這種要讓葉權值 * 深度最小的最多k叉樹,通解就是每層放k - 1個,而後多的一個向下延伸。it

從下往上着構造,要添加0補全。io

而後,能夠用蚯蚓的套路優化常數(有排序的複雜度)。event

若是給定的是有序的或者可以桶排,就能作到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代碼
相關文章
相關標籤/搜索