[ CodeVS冲杯之路 ] P1063

  不充钱,你怎么AC?

  题目:http://codevs.cn/problem/1063/

 

  本来是想写石子合并的,结果把题目看错了,写成了合并果子…… 凑合交了上去,直接A了……

  题目将可以将任意两堆合并,只要要求两堆数量和最小,那么考虑贪心,用堆维护,时间复杂度降为 O(nlog2n)

  维护一个小根堆,每次将堆顶和儿子中较小的那个合并,更新答案

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 
 9 int n,a[10001],ans;
10 void down(int x)
11 {
12     x*=2;
13     if (x>n) return;
14     if (x<n&&a[x]>a[x+1]) x++;
15     if (a[x/2]>a[x])
16         {
17             swap(a[x],a[x/2]);
18             down(x);
19         }
20 }
21 int main()
22 {
23     int i;
24     scanf("%d",&n);
25     for (i=1;i<=n;i++) scanf("%d",&a[i]);
26     sort(a+1,a+n+1);
27     while (n>1)
28         {
29             if (a[2]<a[3]||n==2)
30                 {
31                     a[2]+=a[1];
32                     ans+=a[2];
33                     down(2);
34                 }
35             else
36                 {
37                     a[3]+=a[1];
38                     ans+=a[3];
39                     down(3);
40                 }
41             a[1]=a[n--];
42             down(1);
43         }
44     printf("%d\n",ans);
45     return 0;
46 }

 

posted @ 2016-09-13 13:44  Hadilo  阅读(173)  评论(0编辑  收藏  举报