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;
}

 

posted @ 2017-10-22 20:44  或是七一  阅读(184)  评论(0编辑  收藏  举报