题解:B4107 [CSP-X2024 山东] 刷题

· · 题解

题目简述

小红有 n 道编程题,每到编程题需要的时间为 a_{i}。她要在 m 天内按顺序做完所有题目,不能用多天完成同一道题。每天她还可以求助小明 1 道题,求助的这道题省去做题时间。

求她在 m 天内最长做题时间的最小值.

主要思路

首先注意到一种情况:如果 n \le m 也就是题目数小于规定天数,那么她就可以在任意 n 天每天都问 1 道题,这样答案就为 0

采用算法

暴力搜肯定是想多了,n \le 10^{5}。于是可以采用二分答案的算法,时间复杂度 O(n \log n)

一开始设定变量 lr,然后每次取中间值,判断这个值是否能成为答案,不断压缩区间,最后一个满足条件的值即为答案就是二分答案的思路。

### 判断是否能成为答案 记录一个 $cnt$ 变量,一开始设为 $1$,用于表示现在是第几天;再记录一个 $sum$ 变量,一开始设为 $0$,用于表示当天的做题时间和;还要记录一个 $maxn$ 变量,一开始设为 $0$,用于表示当天最长做题时间。 遍历 $a_{1} \sim a_{n}$,判断 $sum - maxn + a_{i}$ 是否大于 $mid$。由于答案要求最小,所以一定要问做题时间最长的题在代码中表现出来就是减 $maxn$。 如果大于,则开始下一天,将 $cnt$ 自增 $1$,$sum$ 和 $maxn$ 设为 $a_{i}$;否则,只将 $sum$ 加上 $a_{i}$ 即可。 ## AC Code ```cpp #include<map> #include<set> #include<list> #include<stack> #include<queue> #include<cmath> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; #define endl '\n' typedef long long ll; const int N = 1e5 + 10; typedef unsigned int ui; typedef pair<ll,ll> pll; typedef pair<int,int> pii; const double PI = acos(-1.0); typedef unsigned long long ull; // ---------------------------- // ---------------------------- int a[N]; // ---------------------------- inline int read() { int f=1,sum=0;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return sum*f; } void print(int x) { if(x<0){putchar('-');x=-x;} if(x>9){print(x/10);} putchar(char(x%10+'0')); } bool check(int n,int m,int x) { int cnt = 1; int sum = 0; int maxn = 0; for (int i=1;i<=n;i++) { maxn = max(maxn,a[i]); if (sum-maxn+a[i] > x) { cnt++; sum = a[i]; maxn = a[i]; } else sum += a[i]; } return cnt <= m; } int _find(int n,int m,int r) { int l = 0; int ans = 0; while (l <= r) { int mid = (l+r) / 2; if (check(n,m,mid)) { ans = mid; r = mid - 1; } else l = mid + 1; } return ans; } int main() { int r = 0; int n = read(); int m = read(); if (n <= m) { print(0); return 0; } for (int i=1;i<=n;i++) { a[i] = read(); r += a[i]; } // ------------------------ print(_find(n,m,r)); return 0; } ``` ## 后言 本人山东省小学生,有幸参加了 CSP-X2024,这道题在赛场看+想 $15$ 分钟左右,代码 $25$ 分钟左右,最后成功 AC,我甚至觉得挺简单。但是上半场 B 题只拿了 $55$ 就很蒻。