集训第四周(高效算法设计)B题 (二分查找优化题)
---恢复内容开始---
Description
Before the invention of book-printing, it was very hard to make a copy of a book. All the contents had to be re-written by hand by so calledscribers. The scriber had been given a book and after several months he finished its copy. One of the most famous scribers lived in the 15th century and his name was Xaverius Endricus Remius Ontius Xendrianus (Xerox). Anyway, the work was very annoying and boring. And the only way to speed it up was to hire more scribers.
Once upon a time, there was a theater ensemble that wanted to play famous Antique Tragedies. The scripts of these plays were divided into many books and actors needed more copies of them, of course. So they hired many scribers to make copies of these books. Imagine you have m books (numbered ) that may have different number of pages ( ) and you want to make one copy of each of them. Your task is to divide these books among k scribes, . Each book can be assigned to a single scriber only, and every scriber must get a continuous sequence of books. That means, there exists an increasing succession of numbers such that i-th scriber gets a sequence of books with numbers between bi-1+1 and bi. The time needed to make a copy of all the books is determined by the scriber who was assigned the most work. Therefore, our goal is to minimize the maximum number of pages assigned to a single scriber. Your task is to find the optimal assignment.
Input
The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case consists of exactly two lines. At the first line, there are two integers m and k, . At the second line, there are integers separated by spaces. All these values are positive and less than 10000000.
Output
For each case, print exactly one line. The line must contain the input succession divided into exactly k parts such that the maximum sum of a single part should be as small as possible. Use the slash character (`/') to separate the parts. There must be exactly one space character between any two successive numbers and between the number and the slash.
If there is more than one solution, print the one that minimizes the work assigned to the first scriber, then to the second scriber etc. But each scriber must be assigned at least one book.
Sample Input
2
9 3
100 200 300 400 500 600 700 800 900
5 4
100 100 100 100 100
Sample Output
100 200 300 400 500 / 600 700 / 800 900
100 / 100 / 100 / 100 100
这道题首先应该想好思路,这道题其实是一个找限值的过程,比如说一个排列,我划分很多的区间,要求每一个区间都不能大于某个值,设这个值为m,那么这个值最小应该是多少,以例1为例,最小应为900,以例2为例,最小应该为100,为什么?因为你有可能将排列中某一个值划为一个区间,如果你限值小于900,那么900就进不了任何区间,划分就会出问题了
同样我们还可以得出m最大值应该是排列相加的总和(把整个排列划为一个区间)。
既然找好了限值的范围,那么限值有什么用呢?可以使用限值作为划多少区间的依据,我可以从从限值的最小处枚举到最大处,直到限值正好可以使区间划分为k个(注意这里可能有个精度问题)。可是枚举的方法虽然可以找到需求的那个值,但是。。。
超时啊,
虽然数组的长度只有500,但是数组元素的最大值可达一千万,一千万乘以五百是什么概念?这样枚举时间复杂度为m*n,超时。。
最好的方法是二分查找进行优化,以限值去判断,如果说这个限值使得区间划分数大于k,那么限值肯定要再大一些,往右查,反之则往左查
这样的时间复杂度是mlogn,时间性能大大提高...
#include"iostream"
#include"algorithm"
#include"cstring"
#include"cstdio"
using namespace std;
int n,k;
int a[];
long long tot;
int maxa; void Init()
{
cin>>n>>k;
tot=;
maxa=-;
for(int i=; i<n; i++)
{
cin>>a[i];
tot+=a[i];
maxa=max(a[i],maxa);
}
//sort(a,a+n);
} int need(long long num)
{
long long c=;
int sum=;
for(int i=; i<n; i++) if(c+a[i]<=num) c+=a[i];
else
{
c=a[i];
sum++;
}
return sum;
} void print(long long num)
{
int last[];
long long done = ;
memset(last, , sizeof(last));
int remain = k;
for(int i = n-; i >= ; i--)
{
if(done + a[i] > num || i+ < remain)
{
last[i] = ;
remain--;
done = a[i];
}
else
{
done += a[i];
}
}
for(int i = ; i < n-; i++)
{
printf("%d ", a[i]);
if(last[i]) printf("/ ");
}
printf("%d\n", a[n-]);
} void guess()
{
long long l,r,m;
l=maxa;
r=tot;
while(l<r)
{
m=l+(r-l)/;
if(need(m)<=k) r=m;
else l=m+;
}
print(l);
} int main()
{
int T,t;
cin>>T;
t=T;
while(T--)
{
Init();
guess();
}
return ;
}
集训第四周(高效算法设计)B题 (二分查找优化题)的更多相关文章
- 集训第四周(高效算法设计)N题 (二分查找优化题)
原题:poj3061 题意:给你一个数s,再给出一个数组,要求你从中选出m个连续的数,m越小越好,且这m个数之和不小于s 这是一个二分查找优化题,那么区间是什么呢?当然是从1到数组长度了.比如数组长度 ...
- 集训第四周(高效算法设计)C题 (二分查找优化题)
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- 数据结构和算法设计专题之---二分查找(Java版)
1.前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序 2.原理:将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后:将要查找的值和数组的中值 ...
- 南理第八届校赛同步赛-F sequence//贪心算法&二分查找优化
题目大意:求一个序列中不严格单调递增的子序列的最小数目(子序列之间没有交叉). 这题证明贪心法可行的时候,可以发现和求最长递减子序列的长度是同一个方法,只是思考的角度不同,具体证明并不是很清楚,这里就 ...
- js基本算法:冒泡排序,二分查找
知识扩充: 时间复杂度:算法的时间复杂度是一个函数,描述了算法的运行时间.时间复杂度越低,效率越高. 自我理解:一个算法,运行了几次时间复杂度就为多少,如运行了n次,则时间复杂度为O(n). 1.冒泡 ...
- Java数据结构和算法总结-数组、二分查找
前言:在平时开发中数组几乎是最基本也是最常用的数据类型,相比链表.二叉树等又简单很多,所以在学习数据和算法时用数组来作为一个起点再合适不过了.本篇博文的所有代码已上传 github ,对应工程的 ar ...
- 数据结构和算法:Python实现二分查找(Binary_search)
在一个列表当中我们可以进行线性查找也可以进行二分查找,即通过不同的方法找到我们想要的数字,线性查找即按照数字从列表里一个一个从左向右查找,找到之后程序停下.而二分查找的效率往往会比线性查找更高. 一. ...
- C#LeetCode刷题-二分查找
二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...
- Leedcode算法专题训练(二分查找)
二分查找实现 非常详细的解释,简单但是细节很重要 https://www.cnblogs.com/kyoner/p/11080078.html 正常实现 Input : [1,2,3,4,5] key ...
随机推荐
- linux系统资源限制ulimit
ulimit命令用来限制系统用户对shell资源的访问.如果不懂什么意思,下面一段内容可以帮助你理解: 假设有这样一种情况,当一台 Linux 主机上同时登陆了 10 个人,在系统资源无限制的情况下, ...
- 积分图像的应用(一):局部标准差 分类: 图像处理 Matlab 2015-06-06 13:31 137人阅读 评论(0) 收藏
局部标准差在图像处理邻域具有广泛的应用,但是直接计算非常耗时,本文利用积分图像对局部标准差的计算进行加速. 局部标准差: 标准差定义如下(采用统计学中的定义,分母为): 其中. 为了计算图像的局部标准 ...
- AsyncTask官方教程-推荐用AsyncTask少用Thread
Using AsyncTask AsyncTask allows you to perform asynchronous work on your user interface. It perform ...
- APP统计
APP统计就是统计用户使用app的各项指标,比如说日活跃量,页面打开次数,新增用户数量,用户年龄分布,用户地区分布,用户性别分布以及用户使用时间段等等.将统计出来的用户信息进行比对分析,可以服务公司的 ...
- Cenos7 切换单用户模式
CentOS 7在进入单用户的时候和6.x做了很多改变,下面让我们来看看如何进入单用户. 1.重启服务器,在选择内核界面使用上下箭头移动 2.选择内核并按“e” 3.修改参数 将rhgb quiet ...
- .NET 几种数据绑定控件的区别
GridView 控件 GridView 控件以表的形式显示数据,并提供对列进行排序.分页.翻阅数据以及编辑或删除单个记录的功能. 特征:一行一条记录,就像新闻列表一样:带分页功能. DataList ...
- mysql中判断条件
if / case when 判断 SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "m ...
- spring 获取ApplicationContext
第一种:获取根目录下的文件名 ApplicationContext ac = new ClassPathXmlApplicationContext("../mvc-dispatcher-se ...
- linux下PPTP Server测试环境搭建
1.1 服务器软件安装 安裝PPTP Server 所需的软件: 安装PPTP: sudo apt-get install pptpd PPTP Server的软件安装很简单,只需要安装pptpd ...
- CentOS6.8 RPM包安装快速zabbix22
CentOS6.8 RPM包安装快速zabbix22 yum install -y epel-release # yum install -y httpd php php-devel mysql-se ...