NOI2015D. 荷马史诗

荷马史诗

题目描述

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

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

一部《荷马史诗》中有 nnn 种不同的单词,从 111nnn 进行编号。其中第 iii 种单词出现的总次数为 wiw_iwi。Allison 想要用 kkk 进制串 sis_isi 来替换第 iii 种单词,使得其满足如下要求: 对于任意的 1≤i,j≤n, i≠j1 \leq i,j \leq n, \ i \neq j1i,jn, i=j,都有:sis_isi 不是 sjs_jsj 的前缀。

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

一些定义:

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

字符串 Str1\text{Str}_1Str1 被称为字符串 Str2\text{Str}_2Str2 的前缀,当且仅当:存在 1≤t≤m1 \leq t \leq m1tm,使得 Str1=Str2[1…t]\text{Str}_1=\text{Str}_2[1 \ldots t]Str1=Str2[1t]。其中,mmm 是字符串 Str2\text{Str}_2Str2 的长度,Str2[1…t]\text{Str}_2[1 \ldots t]Str2[1t] 表示 Str2\text{Str}_2Str2 的前 ttt 个字符组成的字符串。

输入格式

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

接下来 nnn 行,第 i+1i+1i+1 行包含 111 个非负整数 wiw_iwi,表示第 iii 种单词的出现次数。

输出格式

输出文件包括两行。

第一行输出一个整数,为《荷马史诗》经过重新编码以后的最短长度。

第二行输出一个整数,为保证最短总长度的情况下,最长字符串 sis_isi 的最短长度。

输入数据 1

4 2
1
1
2
2
Copy

输出数据 1

12
2
Copy

输入数据 2

6 3
1
1
3
3
9
9
Copy

输出数据 2

36
3
Copy

数据范围与提示

限制与约定

Case # nnn 的规模 kkk 的规模 附加限制
1 n=3n = 3n=3 k=2k = 2k=2 -
2 n=5n = 5n=5
3 n=16n = 16n=16 所有 wiw_iwi 均相等
4 n=1000n = 1000n=1000 wiw_iwi 在取值范围内均匀随机
5 -
6 n=100000n = 100000n=100000
7 所有 wiw_iwi 均相等
8 -
9 n=7n = 7n=7 k=3k = 3k=3
10 n=16n = 16n=16 所有 wiw_iwi 均相等
11 n=1001n = 1001n=1001
12 n=99999n = 99999n=99999 k=4k = 4k=4
13 n=100000n = 100000n=100000 -
14
15 n=1000n = 1000n=1000 k=5k = 5k=5
16 n=100000n = 100000n=100000 k=7k = 7k=7 wiw_iwi 在取值范围内均匀随机
17 -
18 k=8k = 8k=8 wiw_iwi 在取值范围内均匀随机
19 k=9k = 9k=9 -
20

对于所有数据,保证 2≤n≤100000, 2≤k≤9, 02n100000, 2k9, 0<wi1011。选手请注意使用 646464 位整数进行输入输出、存储和计算。

评分方式

对于每个测试点:
若输出文件的第 111 行正确,得到该测试点 40%40\%40% 的分数;
若输出文件完全正确,得到该测试点 100%100\%100% 的分数。

#include
#include
#include
#include
#define ll long long
using namespace std;
struct node
{
    ll w,h;
    node(){w=0,h=0;}
    node(ll w,ll h):w(w),h(h){}
    bool operator <(const node &a)const{return a.w==w?h>a.h:w>a.w;}
};
ll ans;
priority_queue<node>q;
int main()
{
    ll n,k;ans=0;scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)
    {
        ll w;scanf("%lld",&w);
        q.push(node(w,1));
    }
    while((q.size()-1)%(k-1)!=0)q.push(node(0,1));
    while(q.size()>=k)
    {
        ll h=-1;ll w=0;
        for(int i=1;i<=k;++i)
        {
            node t=q.top();q.pop();
            h=max(h,t.h);
            w+=t.w;
        }
        ans+=w;
        q.push(node(w,h+1));
    }
    printf("%lld\n%lld\n",ans,q.top().h-1);
    return 0;
}

你可能感兴趣的:(NOI,比赛,C++,算法,数据结构,c++,前端,java)