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 = 100001;
 7 int n, m;
 8 int a[N];
 9 int jud(int k){
10     int i;
11     int tt = (n-1)%(k-1);
12     ll t, s = 0;
13     queue<ll>q1, q2;
14     if(tt){
15         for(i = 1; i <= k-1 - tt; ++i)
16             q1.push(0);//虚拟点
17     }
18     for(i = 1; i <= n; ++i)
19         q1.push(a[i]);
20     while(1){
21         t = 0;
22         int x1, x2;
23         for(i = 1; i <= k; ++i){
24             if(q1.empty() && q2.empty())
25                 break;
26             if(q1.empty()){
27                 t += q2.front(); q2.pop();
28                 continue;
29             }
30             if(q2.empty()){
31                 t += q1.front(); q1.pop();
32                 continue;
33             }
34             x1 = q1.front();
35             x2 = q2.front();
36             if(x1 < x2){
37                 t += x1; q1.pop();
38             }else{
39                 t += x2; q2.pop();
40             }
41         }
42         s += t;
43         if(q1.empty() && q2.empty())
44             break;
45         q2.push(t);//维护合并后的值
46     }
47     if(s <= m) return 1;
48     return 0;
49 }
50 void bi_search(){
51     int l = 2,r = n;
52     while(l < r){
53         int mid = l + (r - l)/2;
54         if(jud(mid))
55             r = mid;
56         else
57             l = mid + 1;
58     }
59     printf("%d\n", r);
60 }
61 int main(){
62     int t, i;
63     scanf("%d", &t);
64     while(t--){
65         scanf("%d%d", &n, &m);
66         for(i = 1; i <= n; ++i)
67             scanf("%d", &a[i]);
68         sort(a+1, a+1+n);
69         bi_search();
70     }
71     return 0;
72 }

时间: 2024-11-09 00:21:10

hdu5884 Sort(二分+k叉哈夫曼树)的相关文章

HDU 5884 Sort (二分+k叉哈夫曼树)

题意:n 个有序序列的归并排序.每次可以选择不超过 k 个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问 k最小是多少. 析:首先二分一下这个 k .然后在给定 k 的情况下,这个代价其实就是 k 叉的哈夫曼树问题.然后用两个队列维护一下就好. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string>

HDU 5884 Sort ——(K叉哈夫曼树)

这题真心比较奥义,先见这个人的博客:http://blog.csdn.net/libin66/article/details/52565484 补0的方法是使得其满足成为满K叉树,而其博客中所说的“所以当(n-1)%(k-1)!=0的时候,会出现归并不能最大化个数的情况,这样会影响二分的单调性”我作如下的解释: 至于为什么不加0,sum会变大呢?作如下的解释:因为有一次合并不是最大个数的话,与其让它在后面单独合并增加权值还不如在前面补0合并呢,毕竟我们在算k的时候sum越小越好嘛~ 原先代码如下

两个队列+k叉哈夫曼树 HDU 5884

1 // 两个队列+k叉哈夫曼树 HDU 5884 2 // camp题解: 3 // 题意:nn个有序序列的归并排序.每次可以选择不超过kk个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过TT, 问kk最小是多少. 4 // . 5 // 题解:首先二分一下这个kk.然后在给定kk的情况下,这个代价其实就是kk叉的哈夫曼树问题.因此直接套用哈夫曼树的堆做法即可.复杂度O(nlog^2n) 6 // ?,这样优化一下读入是可以卡过去的. 7 // 然后主代码手表示,利用合并的单调

UOJ#130 【NOI2015】荷马史诗 K叉哈夫曼树

[NOI2015]荷马史诗 链接:http://uoj.ac/problem/130 因为不能有前缀关系,所以单词均为叶子节点,就是K叉哈夫曼树.第一问直接求解,第二问即第二关键字为树的高度. #include< cstdio > #include< algorithm > typedef unsigned long long ull; template inline void read(T&x) { x=0;bool f=0;char c=getchar(); while

【NOI2015】【bzoj4198】【荷马史诗】【k叉哈夫曼树】【贪心】

Description 追逐影子的人,自己就是影子. --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由<奥德赛>和<伊利亚特>组成的鸿篇巨制<荷马史诗>实在是太长了,Allison 想通过一种编码方式使得它变得短一些. 一部<荷马史诗>中有 n 种不同的单词,从 1 到 n 进行编号.其中第 i 种单词出现的总次数为 wi.Allison 想要用 k 进制串 si

2016 年青岛网络赛---Sort(k叉哈夫曼)

题目链接 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

4198: [Noi2015]荷马史诗 (哈夫曼树基础)

一.题目概述 4198: [Noi2015]荷马史诗 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1545  Solved: 818[Submit][Status][Discuss] Description 追逐影子的人,自己就是影子. --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由<奥德赛>和<伊利亚特>组成的鸿篇巨制<荷马史

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int

【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找--方法一:顺序查找(时间复杂度O(n)) int SequentialSearch(St