侧边栏壁纸
博主头像
GabrielxD

列車は必ず次の駅へ。では舞台は?私たちは?

  • 累计撰写 551 篇文章
  • 累计创建 117 个标签
  • 累计收到 9 条评论

目 录CONTENT

文章目录

【二分查找】复制书稿

GabrielxD
2022-12-18 / 0 评论 / 0 点赞 / 16 阅读 / 624 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-12-18,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

题目

1028. 复制书稿


现在要把 mm 本有顺序的书分给 kk 个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三和第四本书给同一个人抄写。

现在请你设计一种方案,使得复制时间最短。

复制时间为抄写页数最多的人用去的时间。

输入格式

第一行两个整数 mkm,k

第二行 mm 个整数,第 ii 个整数表示第 ii 本书的页数。

输出格式

kk 行,每行两个整数,第 ii 行表示第 ii 个人抄写的书的起始编号和终止编号。

kk 行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。

特殊说明,如果一个人没有被安排任何抄写任务,则可用 0 0 来表示。

数据范围

km500k \le m \le 500

输入样例:

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]);
        }
    }
}
0

评论区