BZOJ4198:[NOI2015]荷马史诗

浅谈\(Huffman\)树:https://www.cnblogs.com/AKMer/p/10300870.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=4198

根据题意描述,这就是要你建一棵\(k\)\(Huffman\)树,并且还是棵\(trie\)树。

然后记个深度,权值相同的时候选深度小的,就可以使得最长单词最短了,也就是这棵\(trie\)树会尽量扁。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(nk)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn=2e5+5;

ll sum_len;
ll w[maxn];
int n,tot,k,mx_dep;

ll read() {
    ll x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

struct node {
    ll cnt;
    int dep,id;
    
    node() {}

    node(ll _cnt,int _dep,int _id) {
        cnt=_cnt,dep=_dep,id=_id;
    }

    bool operator<(const node &a)const {
        if(cnt==a.cnt)return dep<a.dep;
        return cnt<a.cnt;
    }
};

struct Heap {
    int tot;
    node tree[maxn];

    void ins(node a) {
        tree[++tot]=a;
        int pos=tot;
        while(pos>1) {
            if(tree[pos]<tree[pos>>1])
                swap(tree[pos],tree[pos>>1]),pos>>=1;
            else break;
        }
    }

    node pop() {
        node res=tree[1];
        tree[1]=tree[tot--];
        int pos=1,son=2;
        while(son<=tot) {
            if(son<tot&&tree[son|1]<tree[son])son|=1;
            if(tree[son]<tree[pos])
                swap(tree[son],tree[pos]),pos=son,son=pos<<1;
            else break;
        }
        return res;
    }
}T;

struct trie {
    int son[maxn][10];

    void calc_ans(int u,int dep) {
        if(!son[u][0]) {
            mx_dep=max(mx_dep,dep);
            sum_len+=w[u]*dep;
            return;
        }
        for(int i=0;i<k;i++)
            calc_ans(son[u][i],dep+1);
    }
}c;

int main() {
    tot=n=read(),k=read();
    for(int i=1;i<=n;i++) {
        w[i]=read();
        T.ins(node(w[i],1,i));
    }
    while((n-1)%(k-1))
        tot++,n++,T.ins(node(0,1,tot));
    while(T.tot!=1) {
        ll tmp=0;int dep=0;++tot;
        for(int i=0;i<k;i++) {
            node word=T.pop();
            c.son[tot][i]=word.id;
            tmp+=word.cnt,dep=max(dep,word.dep);
        }
        T.ins(node(tmp,dep+1,tot));
    }
    c.calc_ans(T.tree[1].id,0);
    printf("%lld\n%d\n",sum_len,mx_dep);
    return 0;
}
posted @ 2019-01-23 21:57  AKMer  阅读(132)  评论(0编辑  收藏  举报