1 条题解
-
0
题目回顾
我们有 棵树,高度为 ,定义不整齐程度为:
我们可以选择交换任意两棵树(也可以不交换),对于每一棵树 ,求交换它和另一棵树后(或自身不交换)整个序列不整齐程度的最小值。
思路总览
1. 基础分析
设原序列的不整齐程度为 。
如果我们交换位置 和 (),那么只有 ,,, 这几条边的值会改变(注意边界情况)。
因此,我们可以先预处理出每个位置在原始序列中的“代价”:
- 对于 ,
- 对于 ,
- 对于 ,
交换 和 后,新的不整齐程度为:
其中 是交换后 和 周围新边的绝对值之和。
2. 交换的三种情况
(a) 交换相邻位置 和
此时只有 ,, 这三条边会变化(注意边界)。这种情况可以 计算。
(b) 交换 和 不相邻()
这时 和 的邻域不相交,所以:
- 对于 ,新边是
- 对于 ,新边是
于是:
$$\text{new\_total} = S - c[i] - c[j] + |h_j - h_{i-1}| + |h_j - h_{i+1}| + |h_i - h_{j-1}| + |h_i - h_{j+1}| $$
3. 核心优化
直接枚举 是 ,不可行。
观察公式:
对于固定的 (),设:
并假设 (否则交换它们)。
那么 的新边贡献是:
这个函数关于 是分段线性的:
- 若 ,则
- 若 ,则
- 若 ,则
4. 数据结构使用
我们需要对每个 ,找到某个 ()使得:
$$\text{score} = -c[i] - c[j] + |h_j - A_1| + |h_j - A_2| + |h_i - B_1| + |h_i - B_2| $$最小,其中 ,。
这可以看作:固定 ,枚举 ,但 的 是固定的,所以我们可以把 的信息按 的值分类存储到线段树中,每个节点存储三种线性函数的最小值(对应 在三个区间的情况)。
5. 代码结构
-
预处理:
- 计算原始总代价
- 计算每个位置的
- 离散化高度
-
相邻交换:
- 直接枚举相邻对 计算
-
与端点交换:
- 交换 与
- 交换 与
- 直接枚举 计算
-
不相邻交换:
- 使用三个线段树(
seg0, seg1, seg2)分别维护 在三个区间的信息 - 按 排序查询和更新
- 对每个 ,根据 与 的关系在线段树中查询最小值
- 使用三个线段树(
6. 线段树设计
每个线段树节点存储一个大小为 3 的数组,表示:
tr[0]:对应 情况下的最小值(形式 )tr[1]:对应 情况下的最小值(常数)tr[2]:对应 情况下的最小值(形式 )
插入/删除时更新,查询时根据 的范围取对应值。
7. 算法复杂度
- 相邻交换和端点交换:
- 不相邻交换:(排序 + 线段树操作)
- 总复杂度:
总结
这道题的关键在于:
- 发现交换只影响局部边
- 将绝对值函数分段线性化
- 使用数据结构维护最优值,避免 枚举
- 注意边界情况的单独处理
核心是分情况处理 + 线段树优化查询,属于经典的数据结构优化问题。
- 1
信息
- ID
- 5122
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者