不充钱,你怎么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 ",ans); 45 return 0; 46 }