• 洛谷 P1281 书的复制(二分答案 输出方案)


    书的复制

    题目背景

    大多数人的错误原因:尽可能让前面的人少抄写,如果前几个人可以不写则不写,对应的人输出 0 0

    不过,已经修改数据,保证每个人都有活可干。

    题目描述

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

    现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

    输入格式

    第一行两个整数 m , k m,k m,k

    第二行 m m m 个整数,第 i i i 个整数表示第 i i i 本书的页数。

    输出格式

    k k k 行,每行两个整数,第 i i i 行表示第 i i i 个人抄写的书的起始编号和终止编号。 k k k 行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。

    样例 #1

    样例输入 #1

    9 3
    1 2 3 4 5 6 7 8 9
    
    • 1
    • 2

    样例输出 #1

    1 5
    6 7
    8 9
    
    • 1
    • 2
    • 3

    提示

    1 ≤ k ≤ m ≤ 500 1\le k \le m \le 500 1km500

    题意:

    P1182 数列分段 Section II的输出方案版本

    思路:

    先二分答案,得出所有人中分得页数最大值的最小值 l,之后利用 l 进行一遍倒序枚举(二分过程中的枚举我们也设置为倒序,这样方便后面的输出方案),将方案存进 x、y 数组,结尾倒序输出方案。

    设置两个数组 x[505],y[505] 表示:各人负责书的起始编号和结束编号。

    注意,假设前面有部分人不必使用时存储的就是00 00,所以需要初始化为00。

    时间复杂度:(sum 表示所有元素之和)

    O ( n l o g s u m ) O(nlogsum) O(nlogsum)

    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    #define int long long
    //#define map unordered_map
    
    //int128 ORZ
    
    /*
    __int128 read() {
    	__int128 x = 0, f = 1;
    	char ch = getchar();
    	while (ch < '0' || ch>'9') {
    		if (ch == '-')f = -1;
    		ch = getchar();
    	}
    	while (ch >= '0' && ch <= '9') {
    		x = x * 10 + ch - '0';
    		ch = getchar();
    	}
    	return x * f;
    }
    
    void print(__int128 x) {
    	if (x < 0) {
    		putchar('-');
    		x = -x;
    	}
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + '0');
    }
    */
    int m, k;
    const int N = 510;
    int a[N], x[N], y[N];
    
    bool check(int ans)
    {
    	int cnt = 1, tmp = 0;
    	for (int i = m; i >= 1; --i)
    	{
    		if (tmp + a[i] <= ans) {
    			tmp += a[i];
    		}
    		else {
    			if (a[i] <= ans) tmp = a[i], ++cnt;
    		}
    	}
    	return cnt <= k;
    }
    
    inline void solve()
    {
    	cin >> m >> k;
    	int r = 0;
    	for (int i = 1; i <= m; ++i)
    	{
    		cin >> a[i], r += a[i];
    	}
    	int l = *max_element(a + 1, a + m + 1);
    
    	while (l < r)
    	{
    		int mid = l + r >> 1;
    		if (check(mid)) r = mid;
    		else l = mid + 1;
    	}
    
    	//初始化为0,由于是全局数组,因此省略
    
    	y[1] = m;	//第一人结束点为 m
    	int tmp = 0, cnt = 1;
    	for (int i = m; i >= 1; --i) {	//倒序遍历
    		if (tmp + a[i] <= l) {
    			tmp += a[i];
    		}
    		else {	//当前书无法给第 cnt 个人抄写
    			if (a[i] <= l) {
    				//  cnt 人开始编号定为 i + 1
    				//  cnt + 1 人结束编号为 i
    				tmp = a[i], x[cnt] = i + 1, y[++cnt] = i;	
    			}
    		}
    	}
    	x[cnt] = 1;	//最后一人起始点为1
    
    	//最后应该倒序输出
    	for (int i = k; i >= 1; --i)
    	{
    		cout << x[i] << " " << y[i] << '\n';
    	}
    }
    
    signed main()
    {
    	//	ios::sync_with_stdio(false);
    	//	cin.tie(nullptr), cout.tie(nullptr);
    
    	int _ = 1; //cin >> _;
    
    	while (_--)
    	{
    		solve();
    	}
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
  • 相关阅读:
    基于SSM的超市管理系统
    kubeadm 升级 k8s集群 1.17到1.20
    掌握递归调用栈思想 由浅入深研究递归
    SOLIDWORKS 3D CAD 2023基础解决方案 新功能Top 10
    R语言ggplot2可视化:基于aes函数中的group参数绘制分组折线图并添加数据点(散点)、geom_point函数中配置数据点形状、大小、颜色、填充色等
    开源大模型与闭源大模型那个更好?
    go语言,拼接字符串有哪些方式
    用原生JS实现虚表控件
    git代码管理工具SourceTree,代码提交分支管理代码拉取,神器啊,开发必备
    【分治算法】【Python实现】二分搜索
  • 原文地址:https://blog.csdn.net/Jacob0824/article/details/128123453