特拉卡
题解
先考虑暴力。
设
可做如下理解:
- 工人
j 处理完毕第i - 1 辆车的时刻为f_{i - 1} + g_j \cdot h_{i - 1} ; - 工人
j 开始处理第i 辆车的时刻为f_i + 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 ,对所有工人取最大值。
答案即为
引入
进一步地:
设点集
给定斜率
那么,对于点集
代码
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;
}