哈夫曼+堆——UOJ#130/Luogu2168 [NOI2015]荷马史诗

来源:互联网 发布:程序员和产品经理关系 编辑:程序博客网 时间:2024/05/22 12:03

题面:Luogu2168 UOJ#130
追逐影子的人,自己就是影子。 ——荷马


这题其实就是一个k叉Huffman树
所以我们用堆维护即可(像合并果子一样做就好了)
不过合并果子可以看作二叉Huffman,这里k叉
没关系,每次选k个合并就好了啊
但是如果(n-1)%(k-1)不等于0的话,那是不可能完全合并掉的
那也没关系,我们把少的用0补上,那就没有问题了
于是这么一道NOI的题就这么被攻下了

#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>#define int long longusing namespace std;struct ppap{int x,y;};bool operator <(ppap a,ppap b){return a.x==b.x?a.y>b.y:a.x>b.x;}priority_queue<ppap>q;signed main(){    int n,k;scanf("%lld%lld",&n,&k);    for(int i=1;i<=n;i++){        int x;scanf("%lld",&x);        q.push((ppap){x,1});    }int sum=n;    if((sum-1)%(k-1)){        for(int i=sum+1;i<=sum+(k-1)-(sum-1)%(k-1);i++)q.push((ppap){0,1});        sum+=(k-1)-(sum-1)%(k-1);    }    int ans=0;    for(;sum>1;sum=sum-k+1){        int a=0,b=0;        for(int i=1;i<=k;i++){            a+=q.top().x;b=max(b,q.top().y);            q.pop();        }        ans+=a;q.push((ppap){a,b+1});    }    printf("%lld\n%lld",ans,q.top().y-1);    return 0;}