训练赛第二场C题 zoj 2339 Hyperhuffman

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2339

解题报告:题目太长了,比赛的时候根本看不懂,完了之后问了什么意思,发现好简单,就是输入n个数据,把这n个数据放入一个集合中,然后每次从集合中取出两个最小的数,求出他们的和,并且把这个和加入到结果当中 ,并且要把这个和放入到集合当中,然后再次从集合中取出两个数,就这样一直做,直到这个集合为空。其实就是用一个最小堆,然后每次从堆里面去粗两个数,求和再把这个和插入到堆中,也就是最裸的堆,要注意的是这题数据范围超出int了,要用long long 。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long INT;
 7 
 8 INT tree[500005];
 9 int rear;
10 
11 void push(INT d)
12 {
13     tree[++rear] = d;
14     int p = rear;
15     while(p/2 >= 1 && tree[p] <= tree[p/2])
16     {
17         swap(tree[p],tree[p/2]);
18         p /= 2;
19     }
20 }
21 
22 INT get_top()
23 {
24     INT d = tree[1];
25     swap(tree[1],tree[rear--]);
26     return d;
27 }
28 
29 void pop(int p)
30 {
31     int i = p , j = 2*p;
32     if(j > rear)
33     return ;
34     if(j + 1 <= rear && tree[j + 1] < tree[j])
35     j++;
36     if(tree[i] >= tree[j])
37     {
38         swap(tree[i],tree[j]);
39         pop(j);
40     }
41     else return;
42 }
43 
44 int main()
45 {
46     int T,n;
47     scanf("%d",&T);
48     while(T--)
49     {
50         scanf("%d",&n);
51         INT sum = 0,d = 0,x = 0;
52         rear = 0;
53         for(int i = 0;i < n;++i)
54         {
55             scanf("%lld",&d);
56             push(d);
57         }
58         for(int i = 1;i<n;++i)
59         {
60             x = get_top();
61             pop(1);
62             x += get_top();
63             pop(1);
64             sum += x;
65             push(x);
66         }
67         printf("%lld
",sum);
68         if(T) printf("
");
69     }
70     return 0;
71 }
View Code
原文地址:https://www.cnblogs.com/xiaxiaosheng/p/3308827.html