题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5884

题意:有n个有序序列,每个序列有ai个元素,现在有一个程序每次可以归并最多k个序列,最终把所有的序列合并成一个,每次归并所需要的代价是所有序列的长度和;

现有一个代价界限T,就是总的代价不能超过T,求符合条件的最小的K;

当给定一个K的准确值时,我们可以每次选择最小的k个数进行合并;所以我们可以用优先队列来处理,但是由于范围比较大,可以优化一下,只让合并形成的序列进入优先队列,每次取数组和队列中较小的一个即可;

对于k可以用二分的方法来求,但是会发现当n=5,k=4的时候,当直接运用上面的做法,最后没有k个数,那么就不能保证单调性了,为了保证每次都是k个序列进行合并,我们可以运用补0的方法进行处理,这样就保证了二分的正确性;

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define met(a, b) memset(a, b, sizeof(a))
#define N 100005
#define INF 0x3f3f3f3f
typedef long long LL; int M, n, a[N], sum[N]; bool Judge(int k)
{
int r = (n-k)%(k-), Index;
LL s;
if(r == )///如果已经满足每次都是k个数了,直接取数组的前k项即可;
{
s = sum[k];
Index = k+;
}
else///否则就先把前r+1个数进行合并;
{
s = sum[r+];
Index = r+;
}
priority_queue<LL>Q;
Q.push(s); while(!Q.empty() || Index <= n)
{
if(Index > n && Q.size() == ) break;///当只剩下队列中的一个数时,说明已经合并完成了; int cnt = ; LL part = ;
while(cnt<k && (!Q.empty() || Index<=n))
{
if(Index <=n && (Q.empty() || a[Index] <= Q.top()))
part += a[Index++];
else
{
part += Q.top();
Q.pop();
}
cnt++;
}
s += part;
if(s > M) break; Q.push(part);
}
return s<=M;
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
met(a, );
met(sum, ); scanf("%d %d", &n, &M); for(int i=; i<=n; i++)
scanf("%d", &a[i]); sort(a, a+n+);
for(int i=; i<=n; i++)
sum[i] = sum[i-] + a[i]; int L = , R = n, ans = ;
while(L <= R)
{
int Mid = (L+R)/;
if(Judge(Mid))
{
R = Mid - ;
ans = Mid;
}
else
L = Mid + ;
}
printf("%d\n", ans);
}
return ;
}
/*
5 15
0 0 0 0 0
*/

Sort---hdu5884(优先队列+二分)的更多相关文章

  1. Sort HDU5884(二分+多叉哈夫曼树)

    HDU5884 Sort 题意:有n个序列要进行归并,每次归并的代价是两个序列的长度的和,要求最终的代价不能超过规定的T,求在此前提下一次能同时进行归并的序列的个数k. 思路:还是太单纯,看完题目一直 ...

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

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

  3. POJ 2010 Moo University - Financial Aid( 优先队列+二分查找)

    POJ 2010 Moo University - Financial Aid 题目大意,从C头申请读书的牛中选出N头,这N头牛的需要的额外学费之和不能超过F,并且要使得这N头牛的中位数最大.若不存在 ...

  4. sort()和优先队列的总结

    一.关于sort函数 sort()排序函数默认是从小到大, a={5,3,2,1,6 }; sort(a,a+n); //输出是1 2 3 5 6 ​这里如果要从到小排序,则有两种方式可以满足 (1) ...

  5. Sort(hdu5884)

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

  6. sort排序与二分查找

    #include<iostream> #include<vector> #include<algorithm> #include<string> usi ...

  7. 给小班讲stl 之 map、sort、优先队列

    引子:最近老师让给小班讲课,讲stl,,但是我觉得就小班现在这水平根本讲不懂好不好,,,,

  8. Gym 101064 D Black Hills golden jewels (二分)

    题目链接:http://codeforces.com/gym/101064/problem/D 问你两个数组合相加的第k大数是多少. 先sort数组,二分答案,然后判断其正确性(判断过程是枚举每个数然 ...

  9. 4 Values whose Sum is 0(二分)

    4 Values whose Sum is 0 Time Limit: 15000MS   Memory Limit: 228000K Total Submissions: 21370   Accep ...

随机推荐

  1. slice、substring和substr

    首先,他们都接收两个参数,slice和substring接收的是起始位置和结束位置(不包括结束位置),而substr接收的则是起始位置和所要返回的字符串长度.直接看下面例子: 1    var tes ...

  2. JavaScript基础知识总结

    正则表达式: 是一种专门用于操作字符串规则. 正则表达式: 通过一些符号来表达,简化对字符串的复杂操作. 弊端:阅读性较差 常见操作: 1.匹配 String matches(regex) 2.获取( ...

  3. COJ975 WZJ的数据结构(负二十五)

    试题描述 输入一个字符串S,回答Q次问题,给你l,r,输出子序列[l,r]的最长连续回文串长度. 输入 第一行为一个字符串S. 第二行为一个正整数Q. 接下来Q行每行为l,r. 输出 对于每个询问,输 ...

  4. 像jQuery那样,采用链式方法,封装一个方法:CSS()

    主要思路就是:返回this对象,将所获取的操作元素放入一个数组中.在原型中添加拓展方法 <html> <head> <title></title> &l ...

  5. Html - Footer

    通用的Footer代码片段 <style> #footer { padding: 20px; text-align: center; background-color: #666; bor ...

  6. Servlet 编程 简单流程处理(重定向)

    流程(来自jiekexueyuan) servlet sucess.jsp error.asp同理 运行结果:

  7. 如何用JavaScript在页面上显示一个时间钟表

    <html><head><script type="text/javascript">function myTime(){var today=n ...

  8. 给php增加gd库(转)

    1.安装zlib tar zxvf zlib-1.2.3.tar.gz cd zlib-1.2.3 ./configure --prefix=/usr/local/zlib make make ins ...

  9. DS实验题 order

    算法与数据结构 实验题 6.4 order ★实验任务 给出一棵二叉树的中序遍历和每个节点的父节点,求这棵二叉树的先序和后序遍历. ★数据输入 输入第一行为一个正整数n表示二叉树的节点数目,节点编号从 ...

  10. Nginx 笔记与总结(12)Nginx URL Rewrite 实例(ecshop)

    访问项目地址:http://192.168.254.100/ecshop 某个商品的 URL:http://192.168.254.100/ecshop/goods.php?id=3 现在需要实现把以 ...