https://www.luogu.org/problem/show?pid=1334
题目描述
瑞瑞想要亲自修复在他的一个小牧场周围的围栏。他测量栅栏并发现他需要N(1≤N≤20,000)根木板,每根的长度为整数Li(1≤Li≤50,000)。于是,他神奇地买了一根足够长的木板,长度为所需的N根木板的长度的总和,他决定将这根木板切成所需的N根木板。(瑞瑞在切割木板时不会产生木屑,不需考虑切割时损耗的长度)瑞瑞切割木板时使用的是一种特殊的方式,这种方式在将一根长度为x的模板切为两根时,需要消耗x个单位的能量。瑞瑞拥有无尽的能量,但现在提倡节约能量,所以作为榜样,他决定尽可能节约能量。显然,总共需要切割N-1次,问题是,每次应该怎么切呢?请编程计算最少需要消耗的能量总和。
输入输出格式
输入格式:
第一行: 整数N,表示所需木板的数量
第2到N+1行: 每行为一个整数,表示一块木板的长度
输出格式:
一个整数,表示最少需要消耗的能量总和
输入输出样例
输入样例#1:
3 8 5 8
输出样例#1:
34
说明
将长度为21的木板,第一次切割为长度为8和长度为13的,消耗21个单位的能量,第二次将长度为13的木板切割为长度为5和8的,消耗13个单位的能量,共消耗34个单位的能量,是消耗能量最小的方案。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdio> 4 #define maxn 20005 5 #define LL long long 6 7 using namespace std; 8 9 LL n,x,size,ans,cnt; 10 LL heap[maxn]; 11 12 void put(LL x) 13 { 14 LL now,next; 15 size++; 16 heap[size]=x; 17 now=size; 18 while(now>1) 19 { 20 next=now/2; 21 if(heap[next]<=heap[now]) break; 22 swap(heap[next],heap[now]); 23 now=next; 24 } 25 } 26 27 void pop() 28 { 29 LL now=1,next; 30 heap[1]=heap[size]; 31 size--; 32 while(now*2<=size) 33 { 34 next=now*2; 35 if(next<size&&heap[next]>heap[next+1]) next++; 36 if(heap[now]<=heap[next]) break; 37 swap(heap[now],heap[next]); 38 now=next; 39 } 40 } 41 42 int main() 43 { 44 scanf("%lld",&n); 45 for(int i=1;i<=n;i++) 46 { 47 cin>>x; 48 put(x); 49 } 50 for(int i=1;i<n;i++) 51 { 52 cnt=heap[1]; pop(); 53 cnt+=heap[1]; pop(); 54 ans+=cnt; 55 put(cnt); 56 } 57 printf("%lld",ans); 58 return 0; 59 }
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #define maxn 20005 5 #define LL long long 6 7 using namespace std; 8 9 LL n,x,size,ans,cnt; 10 priority_queue<LL,vector<LL>,greater<LL> >que; 11 12 int main() 13 { 14 scanf("%lld",&n); 15 for(int i=1;i<=n;i++) 16 { 17 cin>>x; 18 que.push(x); 19 } 20 for(int i=1;i<n;i++) 21 { 22 cnt=que.top(); que.pop(); 23 cnt+=que.top(); que.pop(); 24 ans+=cnt; 25 que.push(cnt); 26 } 27 printf("%lld",ans); 28 return 0; 29 }