这题真心比较奥义,先见这个人的博客:http://blog.csdn.net/libin66/article/details/52565484

  补0的方法是使得其满足成为满K叉树,而其博客中所说的“所以当(n-1)%(k-1)!=0的时候,会出现归并不能最大化个数的情况,这样会影响二分的单调性”我作如下的解释:

  至于为什么不加0,sum会变大呢?作如下的解释:因为有一次合并不是最大个数的话,与其让它在后面单独合并增加权值还不如在前面补0合并呢,毕竟我们在算k的时候sum越小越好嘛~

  原先代码如下(WA):

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
const int N = + ;
typedef long long ll; int n,lim;
int a[N]; bool can(int k)
{
if(k == ) return false;
queue<ll> Q1,Q2;
ll sum = ;
for(int i=;i<=n;i++) Q1.push((ll)a[i]);
while(Q1.size()+Q2.size() > )
{
if(Q1.size()+Q2.size() >= k)
{
ll temp = ;
for(int i=;i<=k;i++)
{
if(Q2.size()==)
{
temp += Q1.front();Q1.pop();
}
else if(Q1.size()==)
{
temp += Q2.front();Q2.pop();
}
else if(Q1.front()<=Q2.front())
{
temp += Q1.front();Q1.pop();
}
else
{
temp += Q2.front();Q2.pop();
}
}
sum += temp;
Q2.push(temp);
}
else
{
ll temp = ;
while(!Q1.empty())
{
temp += Q1.front();Q1.pop();
}
while(!Q2.empty())
{
temp += Q2.front();Q2.pop();
}
sum += temp;
}
}
return sum <= (ll)lim;
} int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&lim);
for(int i=;i<=n;i++) scanf("%d",a+i);
sort(a+,a++n);
int L = , R = n;
int ans = ;
while(L <= R)
{
//printf("!! %d %d\n",L,R);
int mid = L + R >> ;
if(can(mid))
{
ans = mid;
R = mid - ;
}
else L = mid + ;
}
printf("%d\n",ans);
}
return ;
} /*
6
6 120
10 10 10 10 10
*/

WA的代码

  AC代码如下:

 #include<iostream>
//#include<bits/stdc++.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<ctime>
#include<algorithm>
#include<cmath>
#include<vector>
#define showtime fprintf(stderr,"time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
typedef long long LL;
#define MP make_pair
#define PII pair<int,int>
#define PLI pair<long long ,int>
#define PFI pair<double,int>
#define PLL pair<ll,ll>
#define PB push_back
#define F first
#define S second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define debug cout<<"?????"<<endl;
//freopen("1005.in","r",stdin);
//freopen("data.out","w",stdout);
const int INF = 0x7f7f7f7f;
const double eps = 1e-;
const int M = + ;
const int N = + ;
const double PI = acos(-.);
const double E = 2.71828182845904523536;
const int MOD = ;
typedef vector<ll> Vec;
typedef vector<Vec> Mat;
int T,n,a[ + ];
ll m;
bool ok(int k){
queue<ll> q,p;
int t = (n-) % (k-);
// 每次减少k-1个数。一共要减少 (n-1) 个数。 还剩下几个数要和 0 一组了
if(t != ) for(int i = ; i < k - t - ; i ++) q.push();
for(int i = ; i < n ; i ++) q.push(a[i]); ll ans = ;
while(!q.empty() || !p.empty()){
ll tmp = ;
for(int i = ; i < k ; i ++){
if(!q.empty() && !p.empty()){
ll u = q.front() , v = p.front();
if(u < v) tmp += u , q.pop();
else tmp += v , p.pop();
}else if(!q.empty()){
ll u = q.front(); q.pop();
tmp += u;
}else if(!p.empty()){
ll v = p.front() ; p.pop();
tmp += v;
}else break;
}
ans += tmp;
if(q.empty() && p.empty()) break;
p.push(tmp);
}
return ans <= m;
}
void solve(){
int l = , r = n;
while(l < r){
int m = (l+r)>>;
if(ok(m)) r = m;
else l = m + ;
}
cout << l << endl;
}
int main(){
cin >> T;
while(T --){
cin >> n >> m;
for(int i = ; i < n ; i ++) scanf("%d",&a[i]);
sort(a,a+n);
solve();
}
return ;
}

AC代码

HDU 5884 Sort ——(K叉哈夫曼树)的更多相关文章

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

    // 两个队列+k叉哈夫曼树 HDU 5884 // camp题解: // 题意:nn个有序序列的归并排序.每次可以选择不超过kk个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过TT, ...

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

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5884 Problem Description Recently, Bob has just learn ...

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

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

  4. 【CF884D】Boxes And Balls k叉哈夫曼树

    题目大意:给定一个大小为 N 的集合,每次可以从中挑出 2 个或 3 个数进行合并,合并的代价是几个数的权值和,求将这些数合并成 1 个的最小代价是多少. 引理:K 叉哈夫曼树需要保证 \((n-1) ...

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

    [NOI2015]荷马史诗 链接:http://uoj.ac/problem/130 因为不能有前缀关系,所以单词均为叶子节点,就是K叉哈夫曼树.第一问直接求解,第二问即第二关键字为树的高度. #in ...

  6. AcWing:149. 荷马史诗(哈夫曼编码 + k叉哈夫曼树)

    追逐影子的人,自己就是影子. ——荷马 达达最近迷上了文学. 她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>. 但是由<奥德赛>和<伊 ...

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

    题意:n 个有序序列的归并排序.每次可以选择不超过 k 个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问 k最小是多少. 析:首先二分一下这个 k .然后在给定 k 的情况下, ...

  8. bzoj 4198 [ Noi 2015 ] 荷马史诗 —— 哈夫曼编码(k叉哈夫曼树)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4198 第一次写哈夫曼树!看了很多博客. 哈夫曼树 & 哈夫曼编码:https://w ...

  9. P2168 [NOI2015]荷马史诗 k叉哈夫曼树

    思路:哈夫曼编码 提交:1次(参考题解) 题解:类似合并果子$QwQ$ 取出前$k$小(注意如果叶子结点不满的话要补全),合并起来再扔回堆里去. #include<cstdio> #inc ...

  10. BZOJ 4198: [Noi2015]荷马史诗 哈夫曼树 k叉哈夫曼树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4198 https://blog.csdn.net/chn_jz/article/details/7 ...

随机推荐

  1. Eclipse怎么升级版本

    java工程上右键——选择Properties——Project Faces——右边java项选择相应的版本就OK了

  2. 如何用Mvc实现一个列表页面-异步加载

    在接触Mvc后,开始有点觉得很累,什么都要自己做,完全没有WebForm的易用性: 大概用了一个月左右的时候,越用用顺手,就习惯了MVC的这种开发方式,灵活,简洁: 当初学习MVC,网上看资料,都是讲 ...

  3. STL之Deque的使用方法

    STL 中类 stack 实现了一个栈 1)push 能够插入元素 2)pop 移除栈顶元素 使用的时候,需要包含头文件 #include <stack>,stack 被声明如下: nam ...

  4. ubuntu更改apt源为阿里云源

    https://blog.csdn.net/zhangjiahao14/article/details/80554616 https://yq.aliyun.com/articles/704603 h ...

  5. Bridge的数据在内核处理流程

    转:http://blog.sina.com.cn/s/blog_67cc0c8f0101oh33.html 转载一篇Bridge的数据在内核处理流程,文章写的不错啊! (2013-07-05 16: ...

  6. nginx的反向代理的优势,特点于原理(一)

    说到反向代理,首先先说一下反向代理的概念 反向代理(Reverse Proxy)方式是指以代理服务器来接受客户端的连接请求,然后将请求转发给网络上的web服务器(可能是apache,nginx,tom ...

  7. JLINK驱动版本更换

    https://www.segger.com/downloads/jlink/JLink_Windows_V644b.exe 官网版本 Jlink的版本目录C:\Keil_v5\ARM\Segger\ ...

  8. DNS负载均衡与NGINX负载均衡策略

    负载均衡是指的是把请求均匀的分摊到多个服务器上处理.一般常见的负载均衡有两种:①客户端与反向代理服务器之间的DNS负载均衡②反向代理服务器与应用服务器之间的负载均衡(这种负载均衡有很多,可以是webl ...

  9. 二、Nginx多站点配置(参考宝塔的)分析

    一.基于宝塔配置文件分析(站的配置文件) 新增的站点配置即添加server并包含在nginx内 查找文件: 文件内容: 二.伪静态 伪静态是一种可以把文件后缀改成任何可能的一种方法,如果我想把php文 ...

  10. PHP代码执行流程

    怎么样?有点了解了么.说实话,单看这个,我本人是有点懵的,不过,不要怕.咱们来慢慢地看下. 首先,在网上找的信息说PHP代码执行的顺序是这样的,第一步是词法分析,第二步是语法分析,第三步是转化为opc ...