zoukankan      html  css  js  c++  java
  • 两个队列+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
    ",r);
    87     }
    88     return 0;
    89 }
  • 相关阅读:
    利用for循环 修改精灵图背景位置
    添加列表项 避免浏览器反复渲染 Fragment
    向元素添加属性名和属性值
    分割文本节点
    查询、回显 基本功能
    获取注释
    合并文本节点
    Node(节点)的4个操作方法
    setTimeout与setInterval
    javascript循环
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5880773.html
Copyright © 2011-2022 走看看