http://acm.hdu.edu.cn/showproblem.php?pid=5884

参考:https://www.cnblogs.com/jhz033/p/5879452.html

【题意】

n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少。

【思路】

k越大,代价越小,二分k,check k

对于每个k,问题转化为n个结点的最优k叉树,用堆做时间复杂度为O(nlogn),再加上二分总复杂度是O(nlogn^2)

然后T了。。。听说加输入挂可以卡过去

正解是这样的:

原数组排序,预处理时间复杂度O(nlogn)

然后求最优k叉树,用一个队列维护合并后的值,而不需要加入原来的堆里重排序(利用新加入的内结点本身的单调性),每次时间复杂度为O(n)

O(nlogn)+O(logn)*O(n),所以最后时间复杂度是O(nlogn)

n个结点不一定能构成最优k叉树,需要补 k-1-((n-1)%(k-1))个权为0的虚结点。

 #include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
int n;
ll t;
const int maxn=1e5+;
ll a[maxn];
bool judge(int mid){
int cnt=(n-)/(mid-);
queue<ll> Q;
if((n-)%(mid-)!=){
cnt++;
for(int i=;i<(mid--(n-)%(mid-));i++){
Q.push();
}
}
ll ans=;
int l=;
while(cnt--){
ll tmp=;
for(int i=;i<mid;i++){
if(!Q.empty()&&(l>=n||Q.front()<=a[l])){
tmp+=Q.front();
Q.pop();
}else{
tmp+=a[l++];
}
}
ans+=tmp;
Q.push(tmp);
}
if(ans<=t) return true;
return false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%lld",&n,&t);
for(int i=;i<n;i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
int l=,r=n;
while(l<=r){
int mid=(l+r)>>;
if(judge(mid)){
r=mid-;
}else{
l=mid+;
}
}
printf("%d\n",l);
}
return ;
}
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
int n;
ll t;
const int maxn=1e5+;
ll a[maxn];
bool judge(int mid){
queue<ll> Q1,Q2;
for(int i=;i<n;i++) Q1.push(a[i]);
if((n-)%(mid-)!=){
for(int i=;i<(mid--(n-)%(mid-));i++){
Q2.push();
}
}
ll ans=;
while(Q1.size()+Q2.size()>=mid){
ll tmp=;
for(int i=;i<mid;i++){
if(Q1.empty()&&!Q2.empty()){
tmp+=Q2.front();
Q2.pop();
}else if(Q2.empty()&&!Q1.empty()){
tmp+=Q1.front();
Q1.pop();
}else if(!Q1.empty()&&!Q2.empty()){
if(Q1.front()<=Q2.front()){
tmp+=Q1.front();
Q1.pop();
}else{
tmp+=Q2.front();
Q2.pop();
}
}
}
// cout<<tmp<<endl;
ans+=tmp;
Q2.push(tmp);
}
if(ans<=t) return true;
return false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%lld",&n,&t);
for(int i=;i<n;i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
int l=,r=n;
while(l<=r){
int mid=(l+r)>>;
if(judge(mid)){
r=mid-;
}else{
l=mid+;
}
}
printf("%d\n",l);
}
return ;
}

【最优K叉树】hdu 5884 Sort的更多相关文章

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

    这题真心比较奥义,先见这个人的博客:http://blog.csdn.net/libin66/article/details/52565484 补0的方法是使得其满足成为满K叉树,而其博客中所说的“所 ...

  2. HDU 5884 Sort(二分答案+计算WPL的技巧)

    Sort Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

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

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

  4. HDU 5884 Sort (二分)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5884 nn个有序序列的归并排序.每次可以选择不超过kk个序列进行合并,合并代价为这些序列的长度和.总的 ...

  5. HDU 5884 Sort(二分+优先队列)

    http://acm.hdu.edu.cn/showproblem.php?pid=5884 题意:有个屌丝设计了一个程序,每次可以将k个数组进行合并,代价为这k个数组总的长度之和.现在另外一个屌丝要 ...

  6. HDU 5884 Sort

    二分,验证. 二分$k$,然后进行验证.有一个地方需要注意一下:如果$n$个数,每次合并$k$个,最后一次不能合$k$个,那么一开始需要补$0$之后再合并才是最优的.合并的时候用优先队列合并时间复杂度 ...

  7. HDU 5884 Sort(2016年青岛网络赛 G 二分+贪心+小优化)

    好题 题意:给你n<=100000个数,每个数范围[0,1000],然后给你一个最大的代价T,每次最多合并k个数成为一个数,代价为k个数的总和.问最后合成1个数的总代价不大于T的最小k 题解:我 ...

  8. HDU - 5884 Sort (二分答案+贪心)

    有n个数字,你需要把这n个数字合成一个数字,每次只能把k个数字合并成一个,花费为这k个数字的和. 给一个最大花费,问不超过这个最大花费的情况下,k的最小值. Sample Input 1 5 25 1 ...

  9. 贪心(哈夫曼树):HDU 5884 sort

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2QAAAKACAIAAAB8KCy/AAAgAElEQVR4nOy9a5Adx3UmWL+kHxuekU ...

随机推荐

  1. springMVC中ajax和后台数据格式错误

    前台ajax: $.ajax("${pageContext.request.contextPath}/hello",// 发送请求的URL字符串. { dataType : &qu ...

  2. 解决flexpaper读取本地文件问题,JAVA+TOMCAT

    flexpaper是不可以用绝对路径的调用本地或项目外的swf文件的,这个我们就有两种方法,一种是把swf和项目放在同一个目录下面,通过相对路径来获取 另一种是在运行项目的tomcat的server. ...

  3. 在Windows 10删除百度云盘的盘符

    1点击微软图标不放,然后点击R  打开运行命令 2输入  Regedit  进入注册表 3找到以下路径:HKEY_LOCAL_MACHINE  SOFTWARE  Microsoft  Windows ...

  4. sqlserver数据库备份方法

    须事先准备一个工具curl,把它放在c盘.然后,在数据库所在服务器安装7z.最后把这2个存储过程执行,在sqlserver的代理中新建作业,即可实现备份操作. --备份指定数据库到本地和远程指定位置( ...

  5. SQL增删查改语句

    一.增:有4种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> insert into sheet1 va ...

  6. UVA 1151 Buy or Build (最小生成树)

    先求出原图的最小生成树,然后枚举买哪些套餐,把一个套餐内的点相互之间边权为0,直接用并查集缩点.正确性是基于一个贪心, 在做Kruskal算法是,对于没有进入最小生成树的边,排序在它前面的边不会减少. ...

  7. dp 20190618

    C. Party Lemonade 这个题目是贪心,开始我以为是背包,不过也不太好背包,因为这个L都已经是1e9了. 这个题目怎么贪心呢?它是因为这里有一个二倍的关系,所以说val[i]=val[i- ...

  8. mac上使用命令行显示隐藏文件

    终端中输入命令 打开<终端> - 粘贴下面的两行命令执行 defaults write com.apple.finder AppleShowAllFiles TRUEkillall Fin ...

  9. Easier Done Than Said?(应用到的知识)

    memset(b,0,sizeof(b)) 对于大块儿内存的分配,例如int arr[100];定义了数组arr,包含100个元素,如果你写成int arr[100]=0;想将数组全部内容初始化为0, ...

  10. vue 实现走马灯效果

    Part.1  问题 在写一个H5页面时遇到一个需求,头部公告需要滚动变换,需要实现一个走马灯效果 Part.2  实现 我的做法:利用 定时器 + CSS3 变换公告数组的顺序 从而实现走马灯效果 ...