集训第四周(高效算法设计)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 ...
 
随机推荐
- shiro 登录
			
@Controllerpublic class LoginController { @RequestMapping(value="/login") public @Response ...
 - 《windows核心编程系列》二十一谈谈基址重定位和模块绑定
			
每个DLL和可执行文件都有一个首选基地址.它表示该模块被映射到进程地址空间时最佳的内存地址.在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000.对于DLL来说,链接器会将它的首 ...
 - SQL 初级教程学习(六)
			
1.创建视图 CREATE VIEW [Current Product List] ASSELECT ProductID,ProductNameFROM ProductsWHERE Discontin ...
 - Create the first sql server 2016 mobile report;创建 第一个 sqlserver 2016 Mobile report
			
在微软收购了datazen之后,sqlserver2016 集成了mobilereport,mobile report 基于html5,兼容各类主流浏览器,之前ssrs2008 R2中很多chart类 ...
 - 在面试官问你BS和CS区别的时候如何回答??
			
这是我下来整理好的,如果哪里不全,望大家多多指教 C/S是Client/Server的缩写.服务器通常采用高性能的PC.工作站或小型机,并采用大型数据库系统,如Oracle.Sybase.Inform ...
 - jsp中提示修改成功
			
修改成功提示 servert包 request.setAttribute("success", "修改失败"); 效果而 function f(){ var n ...
 - AJPFX分析Android退出应用最优雅的方式
			
什么是RS式呢?即Receiver+singleTask .我们知道Activity有四种加载模式,而singleTask就是其中的一种,使用这个模式之后,当startActivity时,它先会在当前 ...
 - 001原始编译全志r6平台tinav3.0.2系统
			
001原始编译全志r6平台tinav3.0.2系统 2018/6/8 11:32 版本:V1.0 开发板:R6 SDK:tina v3.0.2 1.01原始编译全志r16平台tinav3.0系统: r ...
 - CCF|游戏|Java
			
import java.util.Scanner; public class tyt { public static void main(String[] args) { Scanner in = n ...
 - IE和DOM事件流、普通事件和绑定事件的区别
			
IE和DOM事件流的区别 IE采用冒泡型事件 Netscape(网络信息浏览器)使用捕获型事件 DOM使用先捕获后冒泡型事件 示例: <body> <div> <butt ...