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做哈夫曼樹 但會超時 所以用兩個雙端佇列,乙個儲存原來的值,乙個儲存...