1 条题解
-
0
UOI 2023 Stage 4 Day1 - 数组与部分和 题解
题目概述
给定一个长度为 的整数数组 ,其中每个元素的值在 到 之间。我们可以执行三种操作:
- 取反操作:将数组中所有元素变为相反数
- 前缀和操作:选择任意子区间,将其替换为该子区间的前缀和数组,然后进行归一化(将元素限制在 范围内)
- 后缀和操作:选择任意子区间,将其替换为该子区间的后缀和数组,然后进行归一化
目标是通过最少的操作序列,使得数组中的所有元素都变为非负数。
解题思路
关键观察
- 操作的本质:前缀和和后缀和操作实际上是在对数组进行线性变换,这些变换会改变数组中元素的分布
- 归一化的作用:防止数值溢出,但由于输入范围很小(-1到1),在实际操作中很少会触发
- 对称性:取反操作可以改变整个数组的符号,这为解决某些情况提供了便利
解决方案
题目采用分层解决的策略,从简单情况到复杂情况逐步处理:
情况1:0次操作
直接检查原数组是否已经满足所有元素非负。
情况2:1次操作
检查三种可能的单步操作是否能解决问题:
- 取反操作
- 对整个数组执行前缀和操作
- 对整个数组执行后缀和操作
情况3:2次操作
这是最复杂的情况,需要深入分析:
- 先取反再执行前缀和/后缀和操作
- 分析前缀和数组的性质,寻找合适的操作区间
- 使用凸包优化来高效计算可能的解
算法核心
代码中的核心部分使用凸包优化来寻找满足条件的操作区间:
- 前缀和计算:计算数组的前缀和
pre[i]和前缀和的前缀和ppre[i] - 凸包构建:将问题转化为在二维平面上寻找满足条件的线段
- 二分查找:在凸包上快速找到最优解
特殊情况处理
当上述方法都无法在2步内解决问题时,代码采用一个通用的3步解决方案:
- 如果需要,先执行取反操作
- 对数组后半部分执行前缀和操作
- 对数组前半部分执行后缀和操作
复杂度分析
- 时间复杂度:,主要来自凸包构建和二分查找
- 空间复杂度:,用于存储各种前缀和数组和凸包
代码实现要点
- 操作模拟:实现了三种操作的具体逻辑
- 快速检查:分层检查0、1、2步解决方案
- 凸包优化:使用栈维护凸包,通过二分查找快速确定最优解
- 边界处理:仔细处理各种边界情况,确保算法正确性
总结
这道题的关键在于理解前缀和和后缀和操作对数组的变换效果,并通过分层处理和凸包优化来寻找最优解。算法设计巧妙,既考虑了简单情况的快速解决,又为复杂情况提供了高效的解决方案。
对于竞赛选手来说,这道题考察了以下几个重要能力:
- 对线性变换的理解
- 凸包优化的应用
- 问题分解和分层解决策略
- 边界情况的处理能力
- 1
信息
- ID
- 4089
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者