【NOI】荷马史诗

2023-12-14 14:10
文章标签 noi 荷马史诗

本文主要是介绍【NOI】荷马史诗,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

Allison最近迷上了文学。她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》组成的鸿篇巨制《荷马史诗》实在是太长了,Allison想通过一种编码方式使得它变得短一些。  

一部《荷马史诗》中有 n 种不同的单词,从 1 到 n 进行编号。其中第 i 种单词出现的总次数为 w[i] 。Allison想要用 k 进制串 s[i] 来替换第 i 种单词,使得其满足如下要求:  

对于任意的 1<=i,j<=n , i<>j ,都有: s[i] 不是 s[j] 的前缀。  

现在Allison想要知道,如何选择 s[i] ,才能使替换以后得到的新的《荷马史诗》长度最小。在确保总长度最小的情况下,Allison还想知道最长的 s[i] 的最短长度是多少?  

一个字符串被称为 k 进制字符串,当且仅当它的每个字符是 0 到 k-1 之间(包括 0 和 k−1 )的整数。  

字符串 Str1 被称为字符串 Str2 的前缀,当且仅当:存在 1<=t<=m ,使得 Str1 = Str2[1..t] 。其中, m 是字符串 str2 的长度, str2[1..t] 表示 str2 的前 t 个字符组成的字符串。

 

输入描述 Input Description

输入文件的第 1 行包含 2 个正整数 n,k ,中间用单个空格隔开,表示共有 n 种单词,需要使用 k 进制字符串进行替换。 

接下来 n 行,第 i+1 行包含 1 个非负整数 w[i] ,表示第 i 种单词的出现次数。

 

输出描述 Output Description

输出文件包括 2 行。  第 1 行输出 1 个整数,为《荷马史诗》经过重新编码以后的最短长度。 第 2 行输出 1 个整数,为保证最短总长度的情况下,最长字符串 s[i] 的最短长度。

题目简述

k-进制哈夫曼编码

题解

容易得到每次都是选取最小的k个合并,如果大小相同,要选取编码长度短的

开始要先把一些合并起来,才能使答案最优,原因就不赘述了

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define il inline
#define re register
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=100001;
typedef long long ll;
int n,k,hs;
struct data{int w;ll v;} h[N];
il ll read(){re ll hs=0;re char c=getchar();while(!isdigit(c)) c=getchar();while(isdigit(c)){hs=(hs<<3)+(hs<<1)+c-'0';c=getchar();}return hs;
}
il bool cmp(re data a,re data b){return (a.v==b.v)?(a.w<b.w):(a.v<b.v);
}
il void swim(re int p){re int q=p>>1;re data a=h[p];while(q>0&&cmp(a,h[q])){h[p]=h[q];p=q;q=p>>1;}h[p]=a;
}
il void sink(re int p){re int q=p<<1;re data a=h[p];while(q<=hs){if(q<hs&&cmp(h[q+1],h[q])) q++;if(cmp(a,h[q])) break;h[p]=h[q];p=q;q=p<<1;}h[p]=a;
}
il void insert(re data v){h[++hs]=v;swim(hs);
}
il void pop(){h[1]=h[hs--];sink(1);
}
int main(){n=read();k=read();for(int i=1;i<=n;i++){h[i].v=read();h[i].w=1;}sort(h+1,h+n+1,cmp);hs=n;re ll ans=0,cnt=0;re int maxn;if((n-1)%(k-1)>0){for(int i=1;i<=(n-1)%(k-1)+1;i++){cnt+=h[1].v;//    print();
            pop();}insert((data){2,cnt});ans=cnt;}while(hs>1){cnt=0;maxn=0;for(int i=1;i<=k;i++){cnt+=h[1].v;maxn=max(maxn,h[1].w);pop();//    print();
        }insert((data){maxn+1,cnt});//    print();ans+=cnt;}cout<<ans<<endl<<h[1].w-1<<endl;return 0;
}

 

转载于:https://www.cnblogs.com/ExiledPoet/p/6077055.html

这篇关于【NOI】荷马史诗的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492831

相关文章

NOI大纲——提高组——最小生成树

最小生成树 简介 一个图中可能存在多条相连的边,我们**一定可以从一个图中挑出一些边生成一棵树。**这仅仅是生成一棵树,还未满足最小,当图中每条边都存在权重时,这时候我们从图中生成一棵树(n - 1 条边)时,生成这棵树的总代价就是每条边的权重相加之和。 一个有N个点的图,边一定是大于等于N-1条的。图的最小生成树,就是在这些边中选择N-1条出来,连接所有的N个点。这N-1条边的边权之和是所

CCF NOI 1049.旋转图像

题目描述 输入一个n行m列的黑白图像,将它顺时针旋转90度后输出。 输入 第一行包含两个整数n和m,表示图像包含像素点的行数和列数。1 <= n <= 100,1 <= m <= 100。 接下来n行,每行m个整数,表示图像的每个像素点灰度。相邻两个整数之间用单个空格隔开,每个元素均在0~255之间。 输出 m行,每行n个整数,为顺时针旋转90度后的图像。相邻两个整数之间用单个空格隔开。

CCF NOI 1048.检测矩形

题目描述 给定n*n由0和1组成的矩阵,如果矩阵的每一行和每一列的1的数量都是偶数,则认为符合条件。 你的任务就是检测矩阵是否符合条件,或者在仅改变一个矩阵元素的情况下能否符合条件。 “改变矩阵元素”的操作定义为0变成1或者1变成0。 输入 输入n + 1行,第1行为矩阵的大小n(0 < n < 100),以下n行为矩阵的每一行的元素,元素之间以一个空格分开。 输出 如果矩阵符合条件,

CCF NOI 1047.寻找鞍点

题目描述 给定一个5*5的矩阵,每行只有一个最大值,每列只有一个最小值,寻找这个矩阵的鞍点。鞍点指的是矩阵中的一个元素,它是所在行的最大值,并且是所在列的最小值。 例如:在下面的例子中(第4行第1列的元素就是鞍点,值为8 )。 11 3 5 6 9 12 4 7 8 10 10 5 6 9 11 8 6 4 7 2 15 10 11 20 25 输入 输入包含一个5行5列的矩阵

CCF NOI 1044.最近元素

题目描述 在一个非降序列中,查找与给定值最接近的元素。 输入 第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。 第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。 第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。 接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1

【NOI-题解】1468. 小鱼的航程1074 - 小青蛙回来了1261. 韩信点兵1254. 求车速1265. 爱因斯坦的数学题

文章目录 一、前言二、问题问题:1468. 小鱼的航程问题:1074 - 小青蛙回来了问题:1261. 韩信点兵问题:1254. 求车速问题:1265. 爱因斯坦的数学题 三、感谢 一、前言 本节主要对循环中需要流程控制的题目进行讲解,包括《1468. 小鱼的航程》《1074 - 小青蛙回来了》《1261. 韩信点兵》《1254. 求车速》《1265. 爱因斯坦的数学题》题目。

【NOI】C++程序结构入门之循环结构二-for循环

文章目录 前言一、for循环1.导入2.语法3.使用场景4.条件控制5.小结 二、例题讲解问题:1264 - 4位反序数问题:1085 - 寻找雷劈数问题:1057 - 能被5整除且至少有一位数字是5的所有整数的个数问题:1392 - 回文偶数?问题:1090 - 同因查找问题:1446. 人口增长问题 三、总结四、感谢 前言 在先前的学习旅程中,我们探索了程序设计的基础砖石

【NOI】C++程序结构入门之分支结构二

文章目录 前言一、逻辑运算符1.导入2.逻辑与(&&)3.逻辑或(||)4.逻辑非(!) 二、例题讲解问题:1656. 是两位的偶数吗问题:1658. 游乐设施问题:1659. 是否含有数字5问题:1660. 今天要上课吗问题:1661. 宇航员选拔 三、总结四、感谢 前言 本章节在之前学习的单分支与双分支结构基础上,深入探讨了多条件判断在程序设计中的应用。 通过引入逻辑运

NOI / 1.6编程基础之一维数组(2)

06:校门外的树 描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。 由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树

【NOI-题解】1320. 时钟旋转1323. 扩建花圃问题1462. 小明的游泳时间1565. 成绩(score)1345. 玫瑰花圃

文章目录 一、前言二、问题问题:1320. 时钟旋转问题:1323. 扩建花圃问题问题:1462. 小明的游泳时间问题:1565. 成绩(score)问题:1345. 玫瑰花圃 三、感谢 一、前言 本章节主要对基本运算中整数运算、小数运算题目进行讲解。包括《1320. 时钟旋转》《1323. 扩建花圃问题》《1462. 小明的游泳时间》《1565. 成绩(score)》《1345