問題描述
追逐影子的人,自己就是影子。 ——荷馬輸入格式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 個字元組成的字串。
輸入檔案的第 1 行包含 2 個正整數 n,k,中間用單個空格隔開,表示共有 n 種單詞,需要使用 k 進製字串進行替換。輸出格式接下來 n 行,第 i+1 行包含 1 個非負整數 wi,表示第 i 種單詞的出現次數。
輸出檔案包括 2 行。樣例輸入1:第 1 行輸出 1 個整數,為《荷馬史詩》經過重新編碼以後的最短長度。
第 2 行輸出 1 個整數,為保證最短總長度的情況下,最長字串 si 的最短長度。
4 2樣例輸入2:1 1 2 2
6 3樣例輸出1:1 1
3 3 9 9
12樣例輸出2:2
36此題的解是多叉哈夫曼樹,哈夫曼樹是用於解決最短編碼的一種編碼方法。3
首先,將每種字元視為點,出現次數視為點權,那麼每次選取權最小的k個點合成乙個新點,新點點權等於各點點權和,如此最後只剩乙個點時,就構好了k叉哈夫曼樹,至於具體的編碼,舉個例子說明即可。
如上圖的二叉哈夫曼樹,那麼a的編碼為00,b的編碼為01,c的編碼為1
至於最長編碼的最短長度,實際上就是要求哈夫曼樹的深度盡量小,那麼只需要每次選權值最小且深度深度盡量小的子樹合併即可。
具體實現時,可以將點分成已合併的點和未合併的點,維護兩個佇列的單調性,每次取隊首即可。
**:
#include
#include
#include
#define n 10000005
#define int long long
using namespace std
;struct nodea[n],b[n];
bool operator
int n,k,l1=1,r1,l2=1,r2
;main()
if((n-1)%(k-1))r1+=k-1-(n-1)%(k-1);
sort(a+l1,a+r1+1);
while(r1-l1+r2-l2+2>1)
else if(l2>r2)
else if(a[l1].v+=a[l1].v
; tmp.sum+=a[l1].sum+a[l1].x
; tmp.x+=a[l1].x
; tmp.dep=max(tmp.dep,a[l1].dep+1);
l1++;
}else
i++;
}b[++r2]=tmp;
}printf("%lld\n%lld",b[l2].sum,b[l2].dep);
}
NOI2015 荷馬史詩
題面 追逐影子的人,自己就是影子 荷馬 allison 最近迷上了文學。她喜歡在乙個慵懶的午後,細細地品上一杯卡布奇諾,靜靜地閱讀她愛不釋手的 荷馬史詩 但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,allison 想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中有n種...
NOI 2015 荷馬史詩 k叉哈夫曼樹 堆優化
題目大意 給出n個數字w,代表n個字母出現的次數,給出k。要求用k進製的數字串si替換第i個字母,且替換之後要求替換後的文章無二義性 這裡的無二義性是指對於任意的 1 i,j n i j,都有 si不是sj的字首 求替換後最短的文章的長度 長度len sigma w i strlen si 和這種情...
NOI 2015 荷馬史詩 k叉哈夫曼樹 堆優化
原址 題目大意 給出n個數字w,代表n個字母出現的次數,給出k。要求用k進製的數字串si替換第i個字母,且替換之後要求替換後的文章無二義性 這裡的無二義性是指對於任意的 1 i,j n i j,都有 si不是sj的字首 求替換後最短的文章的長度 長度len sigma w i strlen si 和...