1 条题解
-
0
题目分析
这是一个关于保镖在数轴上移动,保护 VIP 并最大化小费的优化问题。主要难点在于:
- 时间空间范围巨大:达到 10^9 级别
- 查询数量极多:Q 可达 3,000,000
- 需要高效处理:不能对每个查询都重新计算
关键思路
1. 坐标变换
将问题从 (时间, 位置) 空间转换到 (时间+位置, 时间-位置) 空间:
- 对于 VIP i:
st = (T_i + A_i, T_i - A_i),ed = (T_i + |B_i - A_i| + B_i, T_i + |B_i - A_i| - B_i) - 对于查询 j:
(x, y) = (P_j + X_j, P_j - X_j)
这样转换后,保镖在数轴上的移动就变成了在新坐标系中的移动,且速度限制转化为 45 度方向的移动限制。
2. 离散化
由于坐标范围很大但实际用到的点有限(最多 2N 个不同的 x 和 y 坐标),进行离散化处理:
- 收集所有 VIP 的起点和终点的 x, y 坐标
- 排序并去重,建立映射关系
3. 动态规划预处理
定义
dp[i][j]表示从离散化后的坐标(i, j)出发能获得的最大小费。状态转移:
dp[i][j] = max( dp[i+1][j] + wx[i][j] * (bx[i+1] - bx[i]), dp[i][j+1] + wy[i][j] * (by[j+1] - by[j]) )其中:
wx[i][j]:在 x 方向从 i 到 i+1 时,在 y 坐标 j 处能保护的最大 VIP 小费率wy[i][j]:在 y 方向从 j 到 j+1 时,在 x 坐标 i 处能保护的最大 VIP 小费率
4. 凸包优化
对于每个查询,我们需要找到最优路径。这可以转化为在凸包上查询最大值的问题:
- 对于每个离散化的 x 坐标,处理对应的查询
- 使用凸包技巧快速回答:给定斜率,找到截距最大的直线
算法流程
- 读入数据并转换坐标
- 离散化处理
- 预处理
wx和wy数组 - DP 计算
dp数组 - 处理查询:
- 将查询按离散化后的坐标分组
- 对每个坐标使用凸包优化回答查询
复杂度分析
- 预处理:O(N²) 对于 N ≤ 2800 是可接受的
- 查询处理:O((N+Q) log N),对于 Q 很大但凸包优化保证了效率
代码实现要点
- 内存优化:使用 vector 动态分配,避免静态数组过大
- 边界检查:防止数组越界
- 凸包维护:使用单调栈维护上凸壳
- 查询回答:二分查找在凸包上找到最优解
总结
本题的难点在于:
- 坐标变换将问题简化
- 离散化处理大范围数据
- DP 预处理所有可能状态
- 凸包优化快速回答大量查询
通过这种分层处理的方法,将原本看似 O(NQ) 的暴力算法优化到了可接受的范围,是典型的"预处理+优化查询"思路。
- 1
信息
- ID
- 4962
- 时间
- 4000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 7
- 已通过
- 1
- 上传者