zoukankan      html  css  js  c++  java
  • NOI2015 荷马史诗

    题目链接:NOI2015 荷马史诗

    在写题解之前先扯一些闲话

    初识这题是在hzwer的博客上,他写的一篇类似于回忆录中提到了这题。其实OI中有很多类似于哈夫曼的知识——它们看起来看起来不是那么重要,但是如果一旦用到,对于那些不知道的人便是”灭顶之灾“,OI这玩意,很多时候,真的有一部分运气的成分,五六场比赛,不能出现一丝错误,虽然不乏奇迹,但更多的,却是无奈。

    哈夫曼编码是基于哈夫曼树的一种编码方式,注意到题目有这样一句话

    “对于任意的 1 ≤ i, j ≤ n , i ≠ j ,都有:si不是sj的前缀。”

    然后我们在来看到一个哈夫曼编码的例子:



    大家所熟知的哈夫曼树基本上都是二叉的,即用二进制表示

    而题目中要求的是k进制,这基本上是一样的

    在上面的例子中,所有有字母的格子都代表着未加密的字符,由根节点走向它们的路径上的数组成了这个字符的编码,由于每个字符没有子树,所以便不会出现有编码是其它编码的前缀

    由于此时的编码是k进制的,所以每次合并是将k个节点合并成一个节点,

    但是这样就会有一个问题:在合并是会出现一些空的节点

    再推一下会发现:将n个节点合并成1个节点,每次将k个节点合并成一个节点,最终会有$(n-1) mod (k-1)$个节点单独空着无法合并

    所以我们要补一些w为0的节点,若$(n-1) mod (k-1)!=0$,则需补充$(k-1)-(n-1) mod (k-1)$个节点

    最终要求的高度就是所构造的哈夫曼树的高度

    哈夫曼树的合并有点类似于NOIp2004石子合并,不过这里由于$nleq10^5$于是可以直接用优先队列写过去

     1 #include<iostream>
     2 #include<string>
     3 #include<string.h>
     4 #include<stdio.h>
     5 #include<algorithm>
     6 #include<vector>
     7 #include<queue>
     8 #include<map>
     9 using namespace std;
    10 struct node{
    11     long long w;int h;
    12     bool operator <(const node p)const
    13     {
    14         return ((w>p.w) || ((w==p.w) && (h>p.h)));
    15     }
    16 };
    17 priority_queue<node> q;
    18 int n,k;
    19 int main()
    20 {
    21     scanf("%d%d",&n,&k);
    22     int i;
    23     for (i=1;i<=n;i++)
    24     {
    25         long long w;
    26         scanf("%lld",&w);
    27         q.push((node){w,1});
    28     }
    29     int cnt=0;
    30     if ((n-1)%(k-1)!=0) cnt=((k-1)-((n-1)%(k-1)));
    31     for (i=1;i<=cnt;i++) q.push((node){0,1});
    32     long long ans=0;cnt+=n;
    33     while (cnt>1)
    34     {
    35         long long sumw=0;int maxh=0;
    36         for (i=1;i<=k;i++)
    37         {
    38             node p=q.top();q.pop();
    39             sumw+=p.w;maxh=max(p.h,maxh);
    40         }
    41         q.push((node){sumw,maxh+1});cnt-=(k-1);
    42         ans+=sumw;
    43     }
    44     printf("%lld
    ",ans);
    45     node p=q.top();
    46     printf("%d
    ",p.h-1);
    47     return 0;
    48 }
  • 相关阅读:
    adb、monkey常用命令
    震惊!90%的程序员不知道的Java知识!
    Android,重新出发!
    Fiddler 手机抓包 手机联网异常解决方案
    技术贴汇总
    Android开发日常-listview滚动方法梳理
    JavaScript基本语法
    Spring Boot Profile
    Spring Boot配置文件占位符
    @PropertySource和@ImportSource
  • 原文地址:https://www.cnblogs.com/encodetalker/p/9774940.html
Copyright © 2011-2022 走看看