1 条题解
-
0
题目分析
有 门课程, 周时间。每周每门课有一次课,对于每节课可以选择:
- 去上课:获得 熟练度
- 翘课自学:获得 熟练度(可以选任意课程自学)
目标:让所有课程熟练度的最小值最大化。
核心思路
二分答案框架
使用二分答案确定可能的最大最小值 ,检查是否能让所有课程的熟练度都至少达到 。
int l = 1, r = 1e18 + 1; while (l <= r) { int mid = (l + r) / 2; if (check(mid)) l = mid + 1, ans = mid; else r = mid - 1; }可行性检查函数
check(x)关键思想:对于每门课程 ,计算达到熟练度 所需的最少周数。
情况分析
对于课程 :
-
如果
- 主要使用效率更高的方式(上课或自学)
- 需要周数:
-
否则(即 )
- 先用 周获得 熟练度
- 剩余熟练度 必须通过另一种方式获得
- 需要额外周数:$\lceil \frac{x - max(A_i, B_i) \times M}{min(A_i, B_i)} \rceil$
资源分配
- 总可用周数:(每周 节课,共 周)
- 每门课程消耗周数累加,检查是否超过总资源
代码详解
可行性检查函数
int check(int x) { int k = n * m; // 总可用节数 for (int i = 1; i <= n; i++) { int s = max(a[i], b[i]); // 选择更高效的方式 if (s * m >= x) { // 主要使用高效方式即可达到目标 k -= (x + s - 1) / s; // 向上取整 } else { // 需要结合两种方式 k -= m; // 先用m周高效方式 k -= (x - s * m + b[i] - 1) / b[i]; // 剩余用另一种方式 } if (k < 0) return 0; // 资源不足 } return k >= 0; // 资源足够 }注意:这里使用 而不是 ,因为:
- 当 时,另一种方式就是
- 但代码中统一用 处理,这在 时正确,在 时也正确(因为此时 )
边界情况处理
- 向上取整技巧:
(x + s - 1) / s等价于 - 大数处理:使用
long long避免溢出 - 答案范围: 覆盖所有可能情况
算法正确性
单调性
如果 可行,那么所有小于 的值都可行;如果 不可行,那么所有大于 的值都不可行。
最优性
二分找到的是最大的可行 值。
复杂度分析
-
时间复杂度:
- 每次
check函数 - 二分次数
- 总复杂度 ,对于 可接受
- 每次
-
空间复杂度: 存储数组
样例验证
样例1
n=3, m=3 A = [19,4,5], B = [2,6,2]输出:18
验证过程:二分找到最大 使得所有课程熟练度都能达到 18。
样例2
n=2, m=1 A = [9,7], B = [2,6]输出:7
由于只有1周,最优策略是让两门课分别达到 9 和 7,最小值是 7。
总结
本题是典型的二分答案 + 贪心验证问题:
- 二分答案确定可能的最大最小值
- 贪心验证为每门课程选择最优学习策略
- 资源统计确保总周数不超过限制
这种解法高效且易于实现,能够处理大规模数据。
- 1
信息
- ID
- 5535
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者