1 条题解
-
0
自动搬运
来自洛谷,原作者为

Makab
我什么都做不到!搬运于
2025-08-24 22:32:44,当前版本为作者最后更新于2025-04-25 17:32:30,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题解
先考虑暴力。
设 表示开始制造第 辆车的最早时间(有边界 ),, 为原题目中的 ,那么有如下转移:
$$f_i = f_{i - 1} + \max \limits_{j = 1}^{n} (g_j \cdot h_{i - 1} - g_{j - 1} \cdot h_i) $$可做如下理解:
- 工人 处理完毕第 辆车的时刻为 ;
- 工人 开始处理第 辆车的时刻为 ;
- 由题意,有 $f_i + g_{j - 1} \cdot h_i \ge f_{i - 1} + g_j \cdot h_{i - 1}$, 即 $f_i \ge f_{i - 1} + g_j \cdot h_{i - 1} - g_{j - 1} \cdot h_i$,对所有工人取最大值。
答案即为 。这样的时间复杂度为 ,考虑斜率优化。
引入 ,则原式化为:
$$\begin{aligned} f_i &= f_{i - 1} + \max \limits_{j = 1}^{n} (g_j \cdot h_{i - 1} - g_{j - 1} \cdot (k \cdot h_{i - 1})) \\ &= f_{i - 1} + h_{i - 1} \cdot \max \limits_{j = 1}^{n} (g_j - k \cdot g_{j - 1}) \\ \end{aligned} $$进一步地:
设点集 ,令 。
给定斜率 ,求使得 最大,即 最大的一个 。
那么,对于点集 ,维护一个上凸壳,每次二分地求斜率为 的直线与之的切点即可,时间复杂度 。
代码
constexpr int N = 1e5 + 2; int n, m, stk[N], top; /** * f[i]: 第 i 辆车最早开始处理的时刻; * g[i]: 前 i 个工人的系数前缀和; * h[i]: 第 i 辆车的系数; */ ll f[N], g[N], h[N]; double slope(int i, int j) { return (double)(g[i] - g[j]) / (g[i - 1] - g[j - 1]); } int main() { read(n, m); rep(i, 1, n) read(g[i]), g[i] += g[i - 1]; rep(i, 1, m) read(h[i]); rep(i, 1, n) { while (top > 1 && slope(i, stk[top]) > slope(stk[top], stk[top - 1])) --top; stk[++top] = i; } rep(i, 2, m) { int l = 0, r = top, mid; double k = (double)h[i] / h[i - 1]; while (l < r) { mid = (l + r) / 2; if (slope(stk[mid + 1], stk[mid]) > k) l = mid + 1; else r = mid; } f[i] = f[i - 1] + g[stk[l]] * h[i - 1] - g[stk[l] - 1] * h[i]; } printf("%lld\n", f[m] + g[n] * h[m]); return 0; }
- 1
信息
- ID
- 7056
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者