1 条题解
-
0
题目大意
在一条直线上有 个目标,坐标为 。玩家从 出发,只能在坐标为 ( 为整数)的补给点投掷小球。击中坐标为 的目标需要消耗 的能量,移动距离 需要消耗 能量。有 位选手,每位选手的 值不同,需要为每位选手计算击中所有目标的最小总能量。
算法思路
关键观察
- 问题分解:将目标分为左侧()和右侧()两组独立处理
- 投掷点选择:对于每个目标,最优的投掷点要么是前一个补给点,要么是后一个补给点
- 代价函数:总代价可以表示为关于移动次数的二次函数
算法框架
1. 预处理阶段
- 将目标按坐标排序
- 分别处理左侧和右侧的目标
- 计算每个目标从前一个或后一个补给点投掷的最小平方代价
- 记录每个新区间的起始位置
2. 数学建模
设移动 次,总代价为:
$$\text{cost} = t \cdot p + \sum_{i=1}^m (p \cdot d - a_i)^2 $$展开后得到二次函数:
$$\text{cost} = m \cdot d^2 \cdot p^2 + (t - 2d \cdot \sum a_i) \cdot p + \sum a_i^2 $$3. 查询处理
- 对所有查询按 值排序(离线处理)
- 对于每个查询,在可能的区间内寻找使二次函数最小的 值
- 使用前缀和、后缀和加速计算
4. 结果合并
对于每个选手,考虑两种策略组合:
- 左侧使用策略 A,右侧使用策略 B
- 左侧使用策略 B,右侧使用策略 A 取两种组合的最小值作为最终答案
算法复杂度
- 时间复杂度:
- 排序:
- 预处理:
- 查询处理:
- 空间复杂度:
算法优势
- 数学优化:利用二次函数的性质快速求最值
- 分治思想:左右分开处理,降低问题复杂度
- 离线处理:批量处理查询,避免重复计算
- 数值稳定性:使用大整数类型防止中间结果溢出
实现细节
- 使用
__int128类型处理大数运算 - 通过前缀和、后缀和优化区间查询
- 对目标和查询排序以提高缓存效率
- 分别处理左右两侧,最后合并结果
总结
本题通过巧妙的数学建模,将复杂的移动和投掷问题转化为二次函数优化问题,结合分治策略和离线处理,实现了高效的最优解计算。算法在保证正确性的同时,能够处理大规模数据输入。
算法标签:
数学优化分治算法二次规划排序二分前缀和优化离线查询
- 1
信息
- ID
- 4644
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者