这题真心比较奥义,先见这个人的博客: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. jvm GC:垃圾回收的测试与分析

    实验环境: (1)Java版本以及模式: java version "1.8.0_171" Java(TM) SE Runtime Environment (build 1.8.0 ...

  2. 开发工具idea

    https://blog.csdn.net/mashuai720/article/details/79389314

  3. JS基础_while循环

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. count(*),count(1),count(字段)

    如果null参与聚集运算,则除count(*)之外其它聚集函数都忽略null. 如:    ID     DD     1      e     2    null    select  count( ...

  5. Cannot assign to read only property 'exports' of object at webpack ....BaseClient

    网上找了很多资料说是import和export不能一起用,改代码 其实根本原因是es6和es5混合使用造成的兼容性问题 只需要配置.babelrc就可以了 首先安装 npm install -D tr ...

  6. idea中安装git后,代码颜色代表的含义

    idea中安装git以后,代码文件出现了不同的颜色 它们分别表示的含义: 绿色,已经加入控制暂未提交 红色,未加入版本控制 蓝色,加入,已提交,有改动 白色,加入,已提交,无改动 灰色:版本控制已忽略 ...

  7. (九)How to use the audio gadget driver

    Contents [hide]  1 Introduction 2 Audio Gadget Driver 1.0 2.1 Enabling the audio gadget driver 2.2 U ...

  8. python文件操作:文件处理案例

    储存一个文件,文件上有多个用户名,密码,做一个认证的流程程序,首先创建一个文件,文件上输入多个用户名,及对应的密码,然后让客户输入用户名和密码,进行用户名和密码核对,如果输入正确,则的认证成功,bre ...

  9. TextView跑马灯

    TextView跑马灯 textView跑马灯实现:1.定义textView标签的4个属性:android:singleLine="true"//使其只能单行android:ell ...

  10. ble ic

    ti cc25xxnordic nrf24xx nrf51xx nrf52xx Beken bk34xx