【BZOJ】1724 [Usaco2006 Nov]Fence Repair 切割木板
【算法】贪心+堆
#include<cstdio> #include<algorithm> using namespace std; const int maxn=20010; int n,heap[maxn],sz; void heap_push(int x) { heap[++sz]=x;//新数入堆底 int now=sz;//以堆底为起点 while(now>1&&heap[now]<heap[now>>1])//非根节点的父亲>儿子时------注意非根判断 { swap(heap[now],heap[now>>1]);//交换即上推 now>>=1;//转移到父亲 } } int heap_pop() { int ans=heap[1];//取出答案 heap[1]=heap[sz--];//将堆底最后一个元素调上来 int now=1;//以堆顶为起点 while(now<=(sz>>1))//若now有儿子------儿子存在判断 { int next=now<<1;//令next为now的左儿子------儿子赋变量 if(next<sz&&heap[next]>heap[next|1])next++;//now有右儿子且右儿子更小时,令next为右儿子------左右儿子判断---注意右儿子存在判断 if(heap[next]>heap[now])return ans;//若根比儿子小,满足条件,退出 else { swap(heap[now],heap[next]);//交换即下推 now=next;//转移到儿子 } } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int u; scanf("%d",&u); heap_push(u); } long long ans=0; for(int i=1;i<n;i++) { int u=heap_pop(),v=heap_pop(); heap_push(u+v); ans+=u+v; } printf("%lld",ans); return 0; }