兩個佇列 k叉哈夫曼樹 HDU 5884

2022-05-08 21:15:10 字數 1615 閱讀 9938

1

//兩個佇列+k叉哈夫曼樹 hdu 58842//

camp題解:3//

題意:nn個有序序列的歸併排序.每次可以選擇不超過kk個序列進行合併,合併代價為這些序列的長度和.總的合併代價不能超過tt, 問kk最小是多少。4//

.5//題解:首先二分一下這個kk。然後在給定kk的情況下,這個代價其實就是kk叉的哈夫曼樹問題。因此直接套用哈夫曼樹的堆做法即可。複雜度o(nlog^2n)6//

​,這樣優化一下讀入是可以卡過去的。7//

然後主**手表示,利用合併的單調性,可以去掉優先佇列得到o(nlogn)的做法:先對所有數排序,另外乙個佇列維護合併後的值,取值時從兩個序列前端取小的即可。8//

昂:如果(n-1)%(k-1)≠0,要把最小的(n-1)%(k-1)+1個數先合併一下。

910 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18

using

namespace

std;

19#define ll long long

20 typedef pairpii;

21const

int inf = 0x3f3f3f3f;22

const

int mod = 998244353;23

const

int n = 1e5+10;24

const

int maxx = 200010

; 25

#define clc(a,b) memset(a,b,sizeof(a))

26const

double eps = 1e-8;27

void fre()

28void freout()

29 inline int read() while(ch>='

0'&&ch<='

9') return x*f;}

3031

inta[n];

32int

n,m;

33bool check(int

k)40

for(int i=1;i<=n;i++)

43 ll sum=0;44

while(1)54

if(q2.size()==0

) 59 a1=q1.front();

60 a2=q2.front();

61if(a1a1;q1.pop();}

62else 63}

64 sum+=tem;

65if(q1.size()==0&&q2.size()==0) break;66

q2.push(tem);67}

68if(sum>m) return

false;69

else

return

true;70

}7172int

main()

86 printf("

%d\n

",r);87}

88return0;

89 }

K叉哈夫曼樹

哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。哈夫曼樹的構造方法是貪心的每次選最小的幾個節點構造。當k 2k 2 k 2的時候需要預處理一下,因為可能最後一步合併操作的點數不到k個節點,這樣的話就不是最優的了。k 2k 2 k 2預處理方法 當r em ain n 1 mod k 1 0r...

荷馬史詩 k叉哈夫曼樹

題目描述 追逐影子的人,自己就是影子。荷馬 達達最近迷上了文學。但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,達達想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中有 n 種不同的單詞,從 1 到 n 進行編號。其中第 i 種單詞出現的總次數為 wiwi。達達想要用 k ...

HDU 5884 Sort 多叉哈夫曼樹

優先取最小的,因為最先取得加的次數最多 並且 每次最好就合併k個,那麼這種情況時,n 1 k 1 m,m n 所以 n 1 m 1 不為0時,要先取掉 前 n 1 m 1 1個,這樣可以讓後面比較大的數字合併次數減少 一開始用set做哈夫曼樹 但會超時 所以用兩個雙端佇列,乙個儲存原來的值,乙個儲存...