bzoj4198: [Noi2015]荷马史诗

堆+huffman树。

huffman二叉树构造法就是每次把最小的俩个合并起来,构成一个树。

但k叉树每回减少(k-1)个,可能最后会有一个坑位被浪费掉,导致答案增加(用心去感受)

于是我果断回忆去年他们游记里面写到,多余的先合并下。。

然后1A了。。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;

struct Point {
    LL x,b,res;
    
    bool operator < (const Point& rhs) const {
        return x>rhs.x || (x==rhs.x && b > rhs.b);
    }
    
    Point(LL a1=0,LL a2=0,LL a3=0) {x=a1; b=a2;res=a3;}    
}u[20];
priority_queue<Point,vector<Point> > q;
LL n,k,tot,maxb,sum,a,c;

int main() {
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++) {
        scanf("%lld",&a);
        q.push(Point(a,0));
    }
    c=(n-1)%(k-1);
    if(c) {
        for(int i=1;i<=c+1;i++) {
            u[i]=q.top(); q.pop();
            tot+=u[i].x;
            sum+=u[i].res;
            maxb=max(maxb,u[i].b);
        }
        q.push(Point(tot,maxb+1,sum+tot));
    }
    
    while(q.size()>1) {
        tot=maxb=sum=0;
        for(int i=1;i<=k;i++) {
            u[i]=q.top();
            q.pop();
            tot+=u[i].x;
            sum+=u[i].res;
            maxb=max(maxb,u[i].b);
        }
        q.push(Point(tot,maxb+1,sum+tot));
    }
    u[0]=q.top();
    printf("%lld\n%lld\n",u[0].res,u[0].b); 
    return 0;     
}

posted @ 2016-06-28 08:54  invoid  阅读(199)  评论(0编辑  收藏  举报