1 条题解
-
0
题目概述
本题要求构建一个木筏,由 KOI 森林的所有树和 IOI 森林的一个连续区间
[L[k], R[k]]
的树组成。树木必须保持原有顺序,木筏的稳定性定义为所有连续区间的最小高度乘以区间长度的最大值。需要回答多个询问,每个询问指定 IOI 森林的一个区间,求最大稳定性。算法思路
关键观察
- 序列归并:木筏序列是 KOI 森林序列和 IOI 森林区间的归并,保持各自顺序。最优解中,IOI 森林的树通常连续插入在 KOI 森林的某个位置。
- 稳定性计算:稳定性计算等价于求序列中所有连续子数组的最小值乘以子数组长度的最大值(即最大矩形面积问题)。
- 预处理:利用单调栈预处理每个树作为最小值时的左右边界,从而计算纯 KOI 森林的最大稳定性。
算法步骤
-
预处理 KOI 森林:
- 对 KOI 森林的树按高度排序,使用单调栈计算每个树作为最小值时能扩展的左右边界。
- 计算纯 KOI 森林的最大稳定性
al
。
-
预处理 IOI 森林:
- 同样使用单调栈计算每个树作为最小值时的左右边界
[L, R]
。
- 同样使用单调栈计算每个树作为最小值时的左右边界
-
持久化李超线段树:
- 维护直线集合,用于快速查询对于给定区间长度,最大可能稳定性值。
- 根据树的高度排序,逐步插入直线,构建持久化版本以支持历史查询。
-
询问处理:
- 对于每个询问
[L, R]
,使用 RMQ 找到 IOI 森林区间中高度最小的树。 - 查询持久化李超线段树,得到仅包含 IOI 森林区间的可能解。
- 使用树状数组和李超线段树处理跨 KOI 和 IOI 森林的区间,考虑插入位置的影响。
- 对于每个询问
-
合并结果:对于每个询问,取纯 KOI 森林稳定性、纯 IOI 森林区间稳定性和跨区间稳定性的最大值。
代码实现详解
数据结构
- 单调栈:计算每个树作为最小值时的左右边界。
- 持久化李超线段树(
t1
):存储直线y = k*x + b
,支持历史版本查询。 - 树状数组(
t2
):维护前缀最大值。 - 李超线段树(
t3
)和树状数组(t4
):处理跨区间查询。
核心函数
std::vector<long long> max_stability(std::vector<int> A, std::vector<int> B, std::vector<int> L, std::vector<int> R)
- 初始化:读取输入数据,对 KOI 和 IOI 森林的树按高度排序。
- 计算边界:使用链表模拟单调栈,计算每个树的左右边界。
- 构建持久化李超线段树:按高度顺序插入直线,记录每个版本。
- 处理询问:
- 使用 RMQ 找到 IOI 区间的最小高度树。
- 查询持久化李超线段树得到基础解。
- 使用树状数组和李超线段树优化跨区间解。
- 返回结果:收集所有询问的答案。
复杂度分析
- 预处理:单调栈和排序均为
O(N log N)
和O(M log M)
。 - 持久化李超线段树:构建
O(M log M)
,查询O(log M)
。 - 询问处理:每个询问
O(log M)
,总复杂度O(Q log M)
。 - 总体:在数据范围内可行。
算法标签
- 单调栈:用于计算左右边界。
- 持久化线段树:维护历史版本直线集合。
- 李超线段树:高效查询直线最大值。
- 树状数组:维护前缀最大值。
- RMQ:区间最小值查询。
- 离线查询:处理多个询问。
总结
本题通过组合多种高级数据结构,高效解决了序列归并后的最大矩形面积问题。关键点在于预处理每个树的扩展边界,并利用持久化李超线段树快速查询不同区间长度的最大稳定性。算法设计精巧,充分体现了数据结构在优化计算中的重要性。
- 1
信息
- ID
- 3578
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 2
- 已通过
- 1
- 上传者