zoukankan      html  css  js  c++  java
  • BZOJ4198 & 洛谷2168 & UOJ130:[NOI2015]荷马史诗——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4198

    https://www.luogu.org/problemnew/show/P2168

    http://uoj.ac/problem/130

    追逐影子的人,自己就是影子。 ——荷马

    Allison 最近迷上了文学。她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》组成的鸿篇巨制《荷马史诗》实在是太长了,Allison 想通过一种编码方式使得它变得短一些。
    一部《荷马史诗》中有 n 种不同的单词,从 1 到 n 进行编号。其中第 i 种单词出现的总次数为 wi。Allison 想要用 k 进制串 si 来替换第 i 种单词,使得其满足如下要求:
    对于任意的 1≤i,j≤n,i≠j,都有:si 不是 sj 的前缀。
    现在 Allison 想要知道,如何选择 si,才能使替换以后得到的新的《荷马史诗》长度最小。在确保总长度最小的情况下,Allison 还想知道最长的 si 的最短长度是多少?
    一个字符串被称为 k 进制字符串,当且仅当它的每个字符是 0 到 k−1 之间(包括 0 和 k−1)的整数。
    字符串 Str1 被称为字符串 Str2 的前缀,当且仅当:存在 1≤t≤m,使得 Str1=Str2[1..t]。其中,m 是字符串 Str2 的长度,Str2[1..t] 表示 Str2 的前 t 个字符组成的字符串。

    描述就是哈夫曼编码的要求,于是考虑是哈夫曼树。

    (然后发现自己根本不会……怒学一波)

    2进制的哈夫曼树的构建规则就是从最底层往高层建,每次用堆找到权值最小的两个节点,合并后两个节点的父亲的权值为这两个节点权值和,并把其压入堆中。

    至于k进制……emm实际想想的话我们只需要改成一次合并k个就可以了。

    切了切了。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<ext/pb_ds/priority_queue.hpp>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> pii;
    #define fi first
    #define se second
    typedef __gnu_pbds::priority_queue<pii,greater<pii>,__gnu_pbds::pairing_heap_tag> heap;
    const int N=1e5+5;
    inline ll read(){
        ll X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    heap q;
    int n,k;
    ll ans;
    int main(){
        n=read(),k=read();
        for(int i=1;i<=n;i++)q.push(pii(read(),1));
        if((n-1)%(k-1)){
        for(int i=1;i<=k-1-(n-1)%(k-1);i++)q.push(pii(0,1));
        }
        while(q.size()!=1){
        ll sum=0,maxh=0;
        for(int i=1;i<=k;i++){
            sum+=q.top().fi;
            maxh=max(maxh,q.top().se);
            q.pop();
        }
        ans+=sum;
        q.push(pii(sum,maxh+1));
        }
        printf("%lld
    %lld
    ",ans,q.top().se-1);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    python流行的原因
    shell rename directory
    shell if [ -d filename]
    eclipse文本编码格式修改为UTF-8
    egrep 第几列开始
    Java double 精度
    BigDecimal 两种方式
    使用SecureCRT连接ubuntu
    eclipse快速查找一个变量、方法或者类被引用的地方
    我的互联网金融行业经验总结
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9135030.html
Copyright © 2011-2022 走看看