HDU 5884 Sort ——(K叉哈夫曼树)
这题真心比较奥义,先见这个人的博客: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叉哈夫曼树)的更多相关文章
- 两个队列+k叉哈夫曼树 HDU 5884
// 两个队列+k叉哈夫曼树 HDU 5884 // camp题解: // 题意:nn个有序序列的归并排序.每次可以选择不超过kk个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过TT, ...
- 2016 年青岛网络赛---Sort(k叉哈夫曼)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5884 Problem Description Recently, Bob has just learn ...
- hdu5884 Sort(二分+k叉哈夫曼树)
题目链接:hdu5884 Sort 题意:n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少. 题解:先二分k,然后在k给 ...
- 【CF884D】Boxes And Balls k叉哈夫曼树
题目大意:给定一个大小为 N 的集合,每次可以从中挑出 2 个或 3 个数进行合并,合并的代价是几个数的权值和,求将这些数合并成 1 个的最小代价是多少. 引理:K 叉哈夫曼树需要保证 \((n-1) ...
- UOJ#130 【NOI2015】荷马史诗 K叉哈夫曼树
[NOI2015]荷马史诗 链接:http://uoj.ac/problem/130 因为不能有前缀关系,所以单词均为叶子节点,就是K叉哈夫曼树.第一问直接求解,第二问即第二关键字为树的高度. #in ...
- AcWing:149. 荷马史诗(哈夫曼编码 + k叉哈夫曼树)
追逐影子的人,自己就是影子. ——荷马 达达最近迷上了文学. 她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>. 但是由<奥德赛>和<伊 ...
- HDU 5884 Sort (二分+k叉哈夫曼树)
题意:n 个有序序列的归并排序.每次可以选择不超过 k 个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问 k最小是多少. 析:首先二分一下这个 k .然后在给定 k 的情况下, ...
- bzoj 4198 [ Noi 2015 ] 荷马史诗 —— 哈夫曼编码(k叉哈夫曼树)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4198 第一次写哈夫曼树!看了很多博客. 哈夫曼树 & 哈夫曼编码:https://w ...
- P2168 [NOI2015]荷马史诗 k叉哈夫曼树
思路:哈夫曼编码 提交:1次(参考题解) 题解:类似合并果子$QwQ$ 取出前$k$小(注意如果叶子结点不满的话要补全),合并起来再扔回堆里去. #include<cstdio> #inc ...
- BZOJ 4198: [Noi2015]荷马史诗 哈夫曼树 k叉哈夫曼树
https://www.lydsy.com/JudgeOnline/problem.php?id=4198 https://blog.csdn.net/chn_jz/article/details/7 ...
随机推荐
- 作业6:Java虚拟机类加载机制
一.概述 1.定义 虚拟机类加载机制:把类的数据从Class文件加载进内存,并对数据作校验.转换解析和初始化,最终形成可被JVM直接使用的Java类型. 2.与C/C++的不同 Java不在编译时进行 ...
- SQL SERVER中Datetime时间的范围与.net的DateTime对象的区别
对于编写.net程序中我们一般写默认的时间,我们会自动创建一个new DateTime()对象.但与SQL SERVER连用我们就会出现一个时间范围的问题. 今天我就记录一下该时间问题. 我们创建的n ...
- 关于spring中AOP的几件小事
0.AOP简介 AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是穿透OOP的补充. AOP的主要编程对象是切面(aspect),而切面模块化横切关注 ...
- vue-路由动态切换title
router.js { path: '/nav', component: () => import('../view/nav.vue'), meta:{ title:'nav', } }, { ...
- SQL:MYSQL入门
MYSQL(关系型数据库管理系统) 参考手册:http://www.w3school.com.cn/sql/index.asp 给大家讲一下数据库:常见的有 ACCESS.MSSSQL.MYSQL.O ...
- Nginx----请求分发中心
Nginx请求分发中心,需要明确几个基本问题,什么是请求,分发中心是什么,为什么需要分发中心. 什么是请求? Niginx是一款高性能的HTTP服务器,这里的请求当然是指接收客户端发送的http协议请 ...
- 怎么处理Win7系统备份还原提示代码0x80042302的错误?
我们都知道Win7系统自带备份还原功能,可以在电脑遇到小问题时通过还原至之前备份的正常系统来解决,非常的方便.但是有些用户在使用备份还原功能时,系统会提示0x80042302错误,这该怎么办呢?下面好 ...
- Activity的跳转及返回值,activity的生命周期
Activity生命周期 从创建到销毁的生命周期: onCreate()→onStart()→onResume()→onPouse()→onStop()→onDestroy() 从起动到后台再到前台: ...
- CentOS 安装 elasticsearch 注意点
注意点: 1. 从官网下载以 rpm 结尾的软件包 7.3.1版本 下载地址: https://artifacts.elastic.co/downloads/elasticsearch/elastic ...
- CentOS7.x卸载与安装MySQL5.7的操作过程以及编码格式的修改
一.MySQL5.7的卸载 1.1yum方式查看yum是否安装过mysql cd yum list installed mysql* 如或显示了列表,说明系统中有MySQL 如上显示,我已经安装了my ...