Sort

Time Limit: 3000/1000 MS (Java/Others)

Memory Limit: 32768/32768 K (Java/Others)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5884

Problem Description

Recently, Bob has just learnt a naive sorting algorithm: merge sort. Now, Bob receives a task from Alice.

Alice will give Bob N sorted sequences, and the i-th sequence includes ai elements. Bob need to merge all of these sequences. He can write a program, which can merge no more than k sequences in one time. The cost of a merging operation is the sum of the length of these sequences. Unfortunately, Alice allows this program to use no more than T cost. So Bob wants to know the smallest k to make the program complete in time.

Input

The first line of input contains an integer t0, the number of test cases. t0 test cases follow.

For each test case, the first line consists two integers N (2≤N≤100000) and T (∑Ni=1 ai < T < 231).

In the next line there are N integers a1,a2,a3,…,aN(∀i,0≤ai≤1000).

Output

For each test cases, output the smallest k.

Sample Input

1

5 25

1 2 3 4 5

Sample Output

3


解题心得:

  1. 可以看出是一个k叉的哈夫曼树,确定k值的时候只能使用二分法。
  2. 要写k叉的哈夫曼树要克服几个条件,首先给出的数目不符合一个哈夫曼树的时候要填充0来凑数,然后一般写哈夫曼树都是使用优先队列,但是这个题卡掉了优先队列,可以根据合并的有序性来优化,使用两个队列,每次比较队顶元素的大小,取小的就行。
  3. 凑零的个数公式是:k - 1 - (n - 1)%(k - 1)。可以根据这个哈夫曼树的图来了解。


  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. vector <ll> ve;
  5. queue <ll> qu,qu2;
  6. bool checke(ll mid,ll m,ll n)
  7. {
  8. while(!qu.empty())
  9. qu.pop();
  10. while(!qu2.empty())
  11. qu2.pop();
  12. ll ans = 0;
  13. /*如果当前的数目不可以直接得到一个哈夫曼数的时候可以
  14. 添加权值为0的根节点来充凑*/
  15. if((n - 1)%(mid - 1) != 0)
  16. {
  17. ll k = (n - 1)%(mid - 1);
  18. for(int i=0;i<mid-1-k;i++)
  19. qu.push(0);
  20. }
  21. for(int i=0;i<ve.size();i++)
  22. qu.push(ve[i]);
  23. /*可以根据合并的单调性用两个队列来优化时间,优化后的
  24. 时间是O(nlogn);
  25. 如果使用优先队列的复杂度会达到O(n(logn)^2);
  26. */
  27. while(!qu.empty() || !qu2.empty())
  28. {
  29. ll sum = 0;
  30. for(int i=0;i<mid;i++)
  31. {
  32. if(qu.empty() && qu2.empty())
  33. break;
  34. if(qu.empty())
  35. {
  36. sum += qu2.front();
  37. qu2.pop();
  38. }
  39. else if(qu2.empty())
  40. {
  41. sum += qu.front();
  42. qu.pop();
  43. }
  44. else
  45. {
  46. ll a = qu2.front();
  47. ll b = qu.front();
  48. if(a < b)
  49. {
  50. sum += a;
  51. qu2.pop();
  52. }
  53. else
  54. {
  55. sum += b;
  56. qu.pop();
  57. }
  58. }
  59. }
  60. ans += sum;
  61. if(qu.empty() && qu2.empty())
  62. break;
  63. qu2.push(sum);
  64. }
  65. if(ans > m)
  66. return true;
  67. return false;
  68. }
  69. void solve(ll n,ll m)
  70. {
  71. ll r,mid,l;
  72. r = n,l = 0;
  73. while(l < r)
  74. {
  75. mid = (l + r) / 2;
  76. if(checke(mid,m,n))
  77. l = mid+1;
  78. else
  79. r = mid;
  80. }
  81. printf("%lld\n",l);
  82. }
  83. int main()
  84. {
  85. int t;
  86. scanf("%d",&t);
  87. while(t--)
  88. {
  89. ve.clear();
  90. ll n,m;
  91. scanf("%lld%lld",&n,&m);
  92. ll N = n;
  93. while(N--)
  94. {
  95. ll temp;
  96. scanf("%lld",&temp);
  97. ve.push_back(temp);
  98. }
  99. sort(ve.begin(),ve.end());
  100. solve(n,m);
  101. }
  102. }

哈夫曼树:HDU5884-Sort(队列、哈夫曼树)的更多相关文章

  1. hdu5884 Sort(二分+k叉哈夫曼树)

    题目链接:hdu5884 Sort 题意:n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少. 题解:先二分k,然后在k给 ...

  2. bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

    详见vfleaking在discuss里的题解. 收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过. 暴力 ...

  3. 1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP

    1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP 题意 用摄像机观察动物,有两个摄像机,一个可以放在奇数天,一个可以放在偶数天.摄像机在 ...

  4. BZOJ4860 BJOI2017 树的难题 点分治、线段树合并

    传送门 只会线段树……关于单调队列的解法可以去看“重建计划”一题. 看到路径长度$\in [L,R]$考虑点分治.可以知道,在当前分治中心向其他点的路径中,始边(也就是分治中心到对应子树的根的那一条边 ...

  5. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  6. 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

    谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...

  7. poj2528线段树解题报告,离散化+线段树

    题目网址:http://poj.org/problem?id=2528 题意: n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=1 ...

  8. Dynamic Rankings(树状数组套权值线段树)

    Dynamic Rankings(树状数组套权值线段树) 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[ ...

  9. 常见基本数据结构——树,二叉树,二叉查找树,AVL树

    常见数据结构——树 处理大量的数据时,链表的线性时间太慢了,不宜使用.在树的数据结构中,其大部分的运行时间平均为O(logN).并且通过对树结构的修改,我们能够保证它的最坏情形下上述的时间界. 树的定 ...

  10. jquery: json树组数据输出到表格Dom树的处理方法

    项目背景 项目中需要把表格重排显示 处理方法 思路主要是用历遍Json数组把json数据一个个append到5个表格里,还要给每个单元格绑定个单击弹出自定义对话框,表格分了单双行,第一行最后还要改ro ...

随机推荐

  1. 洛谷 P1169||bzoj1057 [ZJOI2007]棋盘制作

    洛谷P1169 bzoj1057 这个题目跟最大全0子矩阵是类似的.正方形的话,只要把任意极大子正方形(”极大“定义见后面的”论文“)当成把某个极大子矩形去掉一块变成正方形即可,容易解决. 解法1:看 ...

  2. po3580SuperMemo(splay)

    链接 操作不少,不过都是一些基本的操作,增删,旋转,逆转,询问最小. 注意一点:T<0时 让t=0: 旋转的时候,是顺时针旋转,数据范围在int内. 刚开始旋转转错方向了.. #include ...

  3. javaoo封装

  4. nginx 配置步骤

    D:\myphp2017\nginx\conf.nginx.conf37行 吧localhost 改为www.ff.com41行取消注释44行 加D:\myphp2017\nginx\html45 在 ...

  5. [Luogu1343]地震逃生 最大流

    题目链接:https://www.luogu.org/problem/show?pid=1343 dinic跑最大流. #include<cstdio> #include<cstri ...

  6. 2189 数字三角形W

    2189 数字三角形W 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold       题目描述 Description 数字三角形要求走到最后mod 100最大 输入描述 ...

  7. CSS3 基本要素概览

    这篇文章将对 CSS 的几个新属性 (text-shadow,box-shadow,and border-radius) 做基本介绍.这些 CSS3 属性通常用来加强页面布局.  RGBA  前面的 ...

  8. github小技巧之Creating a pull request 创建 pull 请求

    创建一个 pull 请求是为了协作更改存储库.这些变化会产生一个分支,它确保主分支保持干净整洁. 与commits提交是不同的,提交是fork之后的一种操作. 在你可以打开一个 pull 请求之前,您 ...

  9. 申请Bing Search API

    地址:https://datamarket.azure.com/home 没有帐号先注册一个,然后登录. 1:在数据中订阅Bing Search API,如果找不到就使用这个地址: https://d ...

  10. codevs 2919 选择题

    时间限制: 1 s  空间限制: 16000 KB  题目等级 : 黄金 Gold 题目描述 Description 某同学考试,在N*M的答题卡上写了A,B,C,D四种答案. 他做完了,又不能交,一 ...