集训第四周(高效算法设计)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 ...
随机推荐
- 我的周记5——"侵略如火,不动如山"
这周发生的事儿 最近同事晋升的参加答辩,还有的同事要转岗走了.难受... 有时候自己常常想,我是不是应该也要走了. 这儿的人好优秀呀,又舍不得离开.但是这里太安逸了,接触不到技术,靠自学呢 又感觉力不 ...
- JavaScript--DOM浏览器窗口可视区域大小
浏览器窗口可视区域大小 获得浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)的方法: 一.对于IE9+.Chrome.Firefox.Opera 以及 Safari: • window.inn ...
- DFS Gym 100553J Jokewithpermutation
题目传送门 /* 题意:将字符串分割成一个全排列 DFS:搜索主要在一位数和两位数的处理,用d1, d2记录个数,在不饱和的情况下,两种都试一下 DFS还是写不来,难道是在家里懒? */ #inclu ...
- 员工管理系统(集合与IO流的结合使用 beta3.0 BufferedReader / ObjectOutputStream)
Employee.java package cn.employee_io; public class Employee { private String empId; private String n ...
- 转 Oracle 12c: Managing Resources
http://www.oracle-class.com/?p=3058 1. Introduction: Oracle database 12c comes with several Resource ...
- 大小写 unix and windows
如果你没有使用工具, 只是sqlplus对大小写不敏感. 如果你要给sql传递参数,且在windows下面就不需要考虑.如果是aix系统,最好写一样.
- if判断的时候明明是null却不走null的函数体?
String phoneStr = String.valueOf(parmMap.get(phone.trim())); if(StringUtils.isBlank(phoneStr) || &qu ...
- java获取公网ip以及物理地址和代理商
package ipconfig; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr ...
- C#过时方法标记
1.当遇到过时或废弃的方式 函数怎么办 [Obsolete]特性解决你的困惑 1.1:当方法已经完成相关兼容 可以保留时
- webpack3.0版本的一些改动
npm install --save / npm install -S 项目发布上线之后还会依赖用到的插件,没有这些插件,项目不能运行 npm install --save-dev / npm ins ...