codevs 1063
贪心题,每次肯定是选最小的两堆。
哈夫曼树裸题,用优先队列维护最小值。
#include<cstdio> #include<cctype> #include<queue> using namespace std; int read(){ char c; while(!isdigit(c=getchar())); int x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x; } priority_queue<int,vector<int>,greater<int> > q; int main(){ int n=read(),ans=0; for(int i=1;i<=n;i+=1) q.push(read()); for(int i=1;i<n;i+=1){ int x=q.top(); q.pop(); x+=q.top(); q.pop(); ans+=x; q.push(x); } printf("%d",ans); return 0; }
单调队列。
先放入一个数组中从小到大sort一遍。
然后选择最小的两个合并,放入一个队列的队尾。
每次最小那个只有可能是数组的队首或者队列的队首。(队列中的数必然是有序的)
时间复杂度还是O(nlogn),但是常数似乎要小一些。
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; int read(){ char c; while(!isdigit(c=getchar())); int x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x; } int h,t,w=1,n,a[10001],b[10001]; int choose(){ if(w<=n && h<t) if(a[w]<b[h]) return a[w++]; else return b[h++]; if(w<=n) return a[w++]; else return b[h++]; } int main(){ n=read(); for(int i=1;i<=n;i+=1) a[i]=read(); sort(a+1,a+n+1); int ans=0; for(t=0;t<n-1;t+=1) ans+=(b[t]=choose()+choose()); printf("%d",ans); return 0; }