书的复制
题目背景
大多数人的错误原因:尽可能让前面的人少抄写,如果前几个人可以不写则不写,对应的人输出 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
1 5
6 7
8 9
提示
1 ≤ k ≤ m ≤ 500 1\le k \le m \le 500 1≤k≤m≤500。
题意:
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;
}