挑战程序设计竞赛p47
注意到木板的分割是一个二叉树,每个最后的Li都是一个叶子节点,所以实质上就是构造哈夫曼树。用快排和插入排序来构造了一个哈夫曼树。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int N;
const int maxn=20005;
int L[maxn];
LL ans;
void Insert_Sort(int lo,int hi){
for(int i=lo+1;i<hi;i++){
for(int j=i;j>lo&&L[j]<L[j-1];j--){
swap(L[j],L[j-1]);
}
}
}
int main(int argc, char const *argv[])
{
cin>>N;
for(int i=0;i<N;i++){
cin>>L[i];
}
sort(L,L+N);
for(int i=1;i<N;i++){
int min=L[i]+L[i-1];
ans+=(long long)min;
L[i]=min;
Insert_Sort(i,N);
}
cout<<ans<<endl;
return 0;
}
要特别小心:插入排序是O(n^2),其实这里很可能是败笔
应该用一个堆来维护有序性质,这样是O(3NlogN)
用堆的写法
#include <iostream>
using namespace std;
const int maxn=20015;
int a[maxn];
void exch(int m,int n){
int t = a[n];
a[n] = a[m];
a[m] = t;
}
void swim(int n){
while(n/2 && a[n]<a[n/2]){
exch(n,n/2);
n/=2;
}
}void sink(int cur,int n){
while(cur*2<=n){
int j=2*cur;
if(j+1<=n && a[j+1]<a[j]) j++;
if(a[cur]<a[j]) break;
exch(cur,j);
cur*=2;
}}
int main(int argc, char const *argv[])
{
int N;
cin>>N;
for(int i=1;i<=N;i++){
cin>>a[i];
swim(i);
}
long long ans=0;
for(int i=N;i>1;){
int first=a[1];
a[1]=a[i--];
sink(1,i);
int second=a[1];
a[1]=a[i];
sink(1,i-1);
ans+=first+second;
a[i]=first+second;
swim(i);
}
cout<<ans<<endl;
return 0;
}
全部换成long long 即可,因为后面会很大。。。。。。。。。。没注意数据范围的zz