两个队列+k叉哈夫曼树 HDU 5884
生活随笔
收集整理的這篇文章主要介紹了
两个队列+k叉哈夫曼树 HDU 5884
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 // 兩個隊列+k叉哈夫曼樹 HDU 5884
2 // 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個數先合并一下。
9
10 #include <iostream>
11 #include <algorithm>
12 #include <cstring>
13 #include <cstdio>
14 #include <vector>
15 #include <cmath>
16 #include <map>
17 #include <queue>
18 using namespace std;
19 #define LL long long
20 typedef pair<int,int> pii;
21 const 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))
26 const double eps = 1e-8;
27 void fre() {freopen("in.txt","r",stdin);}
28 void freout() {freopen("out.txt","w",stdout);}
29 inline int read() {int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch=getchar();}while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
30
31 int a[N];
32 int n,m;
33 bool check(int k){
34 queue<LL>q1;
35 queue<LL>q2;
36 if((n-1)%(k-1)!=0){
37 for(int i=1;i<=k-1-(n-1)%(k-1);i++)
38 q1.push(0);
39 }
40 for(int i=1;i<=n;i++){
41 q1.push(a[i]);
42 }
43 LL sum=0;
44 while(1){
45 LL tem=0;
46 for(int i=1;i<=k;i++){
47 if(q1.size()==0&&q2.size()==0) break;
48 int a1,a2;
49 if(q1.size()==0){
50 tem+=q2.front();
51 q2.pop();
52 continue;
53 }
54 if(q2.size()==0) {
55 tem+=q1.front();
56 q1.pop();
57 continue;
58 }
59 a1=q1.front();
60 a2=q2.front();
61 if(a1<a2) {tem+=a1;q1.pop();}
62 else {tem+=a2;q2.pop();}
63 }
64 sum+=tem;
65 if(q1.size()==0&&q2.size()==0) break;
66 q2.push(tem);
67 }
68 if(sum>m) return false;
69 else return true;
70 }
71
72 int main(){
73 // fre();
74 int T;
75 scanf("%d",&T);
76 while(T--){
77 scanf("%d%d",&n,&m);
78 for(int i=1;i<=n;i++) scanf("%d",&a[i]);
79 sort(a+1,a+1+n);
80 int l=2,r=n;
81 while(l<r){
82 int mid=(l+r)>>1;
83 if(check(mid)) r=mid;
84 else l=mid+1;
85 }
86 printf("%d\n",r);
87 }
88 return 0;
89 }
?
轉載于:https://www.cnblogs.com/ITUPC/p/5880773.html
總結
以上是生活随笔為你收集整理的两个队列+k叉哈夫曼树 HDU 5884的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为鸿蒙机顶盒,华为暗中放弃电视盒子业务
- 下一篇: Nimbus三Storm源码分析--Ni