#xLYHDPybttg050603. 1608:【 例 3】任务安排 3

1608:【 例 3】任务安排 3

好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:


题目描述

NN 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。机器会把这 NN 个任务分成若干批,每一批包含连续的若干个任务。从时刻 00 开始,任务被分批加工,执行第 ii 个任务所需的时间是 TiT_i。另外,在每批任务开始前,机器需要 SS 的启动时间,故执行一批任务所需的时间是启动时间 SS 加上每个任务所需时间之和。

一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。也就是说,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数 CiC_i

请为机器规划一个分组方案,使得总费用最小。


输入格式

第一行两个整数 N,SN, S

接下来 NN 行,每行两个整数 Ti,CiT_i, C_i


输出格式

输出一个整数,表示最小的总费用。


样例

样例输入

5 1
1 3
3 2
4 3
2 3
1 4

样例输出

153

样例说明

与前面两题样例相同,数据规模更大,TiT_i 可能为负数。


数据范围

对于全部数据:

  • 1N3×1051 \le N \le 3\times 10^5
  • 1S281 \le S \le 28
  • Ti28|T_i| \le 28
  • 0Ci280 \le C_i \le 28

时空限制

  • 时间:1000 ms1000 \text{ ms}
  • 内存:524288 KB524288 \text{ KB}

提示
此题为 任务安排 系列中的较难版本,TiT_i 可能为负数,导致 sumT[i]\text{sumT}[i] 不再单调递增,斜率优化时不能直接弹出队首,而需要在队列中二分查找最优决策点。

状态转移方程(同前):

$$dp[i] = \min_{0 \le j < i} \left\{ dp[j] + \text{sumT}[i] \times (\text{sumC}[i] - \text{sumC}[j]) + S \times (\text{sumC}[N] - \text{sumC}[j]) \right\}$$

化简为:

$$dp[i] = \min_{0 \le j < i} \left\{ dp[j] - (\text{sumT}[i] + S) \times \text{sumC}[j] \right\} + \text{sumT}[i] \times \text{sumC}[i] + S \times \text{sumC}[N]$$

A[j]=sumC[j]A[j] = \text{sumC}[j], $B[j] = dp[j] - (\text{sumT}[j] + S) \times \text{sumC}[j]$(注意这里与任务安排 2 的 B[j]B[j] 定义不同,因为 sumT[i]\text{sumT}[i]jj 无关)。

更准确的是: 令 X[j]=sumC[j]X[j] = \text{sumC}[j], Y[j]=dp[j]S×sumC[j]Y[j] = dp[j] - S \times \text{sumC}[j],则:

$$dp[i] = \min_{0 \le j < i} \left\{ Y[j] - \text{sumT}[i] \times X[j] \right\} + \text{sumT}[i] \times \text{sumC}[i] + S \times \text{sumC}[N]$$

这是形如 dp[i]=min{Y[j]kiX[j]}dp[i] = \min\{ Y[j] - k_i \cdot X[j] \} 的形式,其中 ki=sumT[i]k_i = \text{sumT}[i]

斜率优化: 对于两个决策 j1<j2j_1 < j_2,决策 j2j_2 优于 j1j_1 的条件为:

$$\frac{Y[j_2] - Y[j_1]}{X[j_2] - X[j_1]} \le \text{sumT}[i]$$

由于 sumT[i]\text{sumT}[i] 可能不单调(TiT_i 可能为负),我们不能直接弹出队首,而需要在单调队列(维护下凸包)中二分查找第一个斜率大于 sumT[i]\text{sumT}[i] 的点,该点左侧的点更优。

步骤

  1. 计算前缀和 sumT[i]\text{sumT}[i], sumC[i]\text{sumC}[i]
  2. 初始化队列,将 j=0j=0 入队(X[0]=0,Y[0]=0X[0]=0, Y[0]=0);
  3. 遍历 ii11NN
    • 在队列中二分查找最优决策 jj,满足斜率 sumT[i]\le \text{sumT}[i] 的最大位置;
    • 用该 jj 计算 dp[i]dp[i]
    • (X[i],Y[i])(X[i], Y[i]) 加入队尾,维护凸包(下凸)性质:若队尾两点与 ii 形成上凸,则弹出队尾;
  4. 输出 dp[N]dp[N]

复杂度 O(NlogN)O(N \log N),因为每个点入队一次,出队一次,但二分查找需要 O(logN)O(\log N)

注意

  • Ci0C_i \ge 0,所以 X[i]=sumC[i]X[i] = \text{sumC}[i] 严格单调递增,可以用二分;
  • 由于 TiT_i 可能为负,sumT[i]\text{sumT}[i] 不单调,所以不能简单弹出队首,必须二分;
  • 本题数据范围较大,注意使用 long long 存储中间结果。

代码框架

  • 队列中存储决策点的下标;
  • 二分时比较斜率 $(Y[q[mid+1]] - Y[q[mid]]) / (X[q[mid+1]] - X[q[mid]])$ 与 sumT[i]\text{sumT}[i]
  • 因为都是整数,可以避免浮点数比较,用乘法判断。