题目
现在要把 本有顺序的书分给 个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三和第四本书给同一个人抄写。
现在请你设计一种方案,使得复制时间最短。
复制时间为抄写页数最多的人用去的时间。
输入格式
第一行两个整数 。
第二行 个整数,第 个整数表示第 本书的页数。
输出格式
共 行,每行两个整数,第 行表示第 个人抄写的书的起始编号和终止编号。
行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。
特殊说明,如果一个人没有被安排任何抄写任务,则可用 0 0
来表示。
数据范围
输入样例:
9 3
1 2 3 4 5 6 7 8 9
输出样例:
1 5
6 7
8 9
解题
方法一:二分查找
思路
二分每个人需要抄写的最大页数(左边界)。
然后倒序遍历所有书,根据最大页数为每个人划分要抄写的书(尽可能让前面的人少抄写)。
代码
import java.util.*;
import java.io.*;
public class Main {
static int m, k;
static int[] a;
static boolean check(int mid) {
int cnt = 0, curr = 0;
for (int x : a) {
if (x + curr <= mid) curr += x;
else {
if (++cnt > k) return false;
curr = x;
}
}
if (curr > 0) ++cnt;
return cnt <= k;
}
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
m = (int) in.nval;
in.nextToken();
k = (int) in.nval;
a = new int[m];
int l = 0, r = 0;
for (int i = 0; i < m; ++i) {
in.nextToken();
int x = (int) in.nval;
l = Math.max(l, x);
r += x;
a[i] = x;
}
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
int[][] ans = new int[k][2];
int prev = m, curr = 0, cnt = 0, idx = 0;
for (int i = m - 1; i >= 0; --i) {
if (a[i] + curr <= l) curr += a[i];
else {
ans[idx][0] = i + 2;
ans[idx][1] = prev;
++idx;
prev = i + 1;
curr = a[i];
++cnt;
}
}
if (prev > 0) {
++cnt;
ans[idx][0] = 1;
ans[idx][1] = prev;
}
while (k-- > 0) {
System.out.println(ans[k][0] + " " + ans[k][1]);
}
}
}
评论区