zoukankan      html  css  js  c++  java
  • hdu5884 Sort(二分+k叉哈夫曼树)

    题目链接:hdu5884 Sort

    题意:n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少。

    题解:先二分k,然后在k给定的情况下,构造k叉哈夫曼树。O(nlogn)的做法:先对所有数排序,另外一个队列维护合并后的值,取值时从两个序列前端取小的即可。

    注:如果(n-1)%(k-1)!=0,那么就要增加(k-1-(n-1)%(k-1))个权值为0的叶子节点作虚拟点。

     1 #include<cstdio>
     2 #include<queue>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 const int N = 100005;
     7 int n, m;
     8 int a[N];
     9 queue<ll>q1, q2;
    10 int jud(int k){
    11     while(!q1.empty()) q1.pop();
    12     while(!q2.empty()) q2.pop();
    13     //queue<ll>q1, q2;
    14     int i;
    15     int tt = (n-1)%(k-1);
    16     ll t, s = 0;
    17     if(tt){
    18         for(i = 1; i <= k-1 - tt; ++i)
    19             q1.push(0);//虚拟点
    20     }
    21     for(i = 1; i <= n; ++i)
    22         q1.push(a[i]);
    23     while(1){
    24         t = 0;
    25         int x1, x2;
    26         for(i = 1; i <= k; ++i){
    27             if(q1.empty() && q2.empty())
    28                 break;
    29             if(q1.empty()){
    30                 t += q2.front(); q2.pop();
    31                 continue;
    32             }
    33             if(q2.empty()){
    34                 t += q1.front(); q1.pop();
    35                 continue;
    36             }
    37             x1 = q1.front();
    38             x2 = q2.front();
    39             if(x1 < x2){
    40                 t += x1; q1.pop();
    41             }else{
    42                 t += x2; q2.pop();
    43             }
    44         }
    45         s += t;
    46         if(q1.empty() && q2.empty())
    47             break;
    48         q2.push(t);//维护合并后的值
    49     }
    50     if(s <= m) return 1;
    51     return 0;
    52 }
    53 void bi_search(){
    54     int l = 2,r = n;
    55     while(l < r){
    56         int mid = l + (r - l)/2;
    57         if(jud(mid))
    58             r = mid;
    59         else
    60             l = mid + 1;
    61     }
    62     printf("%d
    ", r);
    63 }
    64 int main(){
    65     int t, i;
    66     scanf("%d", &t);
    67     while(t--){
    68         scanf("%d%d", &n, &m);
    69         for(i = 1; i <= n; ++i)
    70             scanf("%d", &a[i]);
    71         sort(a+1, a+1+n);
    72         bi_search();
    73     }
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    Virt-install用法:
    kvm笔记
    配置centos7解决 docker Failed to get D-Bus connection 报错
    linux系统下的用户文件句柄数限制
    Linux下如何通过命令检查网卡是否插上网线
    data命令详解
    cron job 里面,如何让脚本半分钟运行一次?
    bash编程之循环控制:
    bash编程之case语句,函数
    0129集训授课——面向对象思想(一):封装与抽象
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/5883180.html
Copyright © 2011-2022 走看看