本文同步发表于我的 洛谷博客。
一、引入
1.1 定长滑窗问题:
给出一列 n n n 个正整数,和一个固定长度为 k k k 的滑动窗口, 从左到右在数列中滑动这个窗口,找到数列中每个窗口内的最大值。
即对于给定数列 A 1 ∼ A n A_1\sim A_n A1∼An ( 1 ≤ n ≤ 1 0 7 ) (1\le n\le 10^7) (1≤n≤107),求每一个 f i = min j = i − k + 1 i A j f_i=\min\limits_{j=i-k+1}^{i}A_j fi=j=i−k+1miniAj。
二、数据维护
2.0 线段树,RMQ
这两者与 2.1 都是 Θ ( n log n ) \Theta(n\log n) Θ(nlogn) 级别的复杂度,且代码量较大,因此略过。
2.1 多重集
2.1.1 简介
multiset 是 STL 容器中的一种,中文名为多重集。多重集是按照特定顺序存储元素的容器,其中多个元素可以具有相等的值。
其底层数据结构为红黑树,是一种高度平衡的二叉搜索树,因此插入,搜索和删除都是 Θ ( log n ) \Theta (\log n) Θ(logn) 的复杂度,而对于根节点的访问则是 Θ ( 1 ) \Theta(1) Θ(1) 的。
2.1.2 解决方法
每一次插入新的元素,并删除旧元素。由于 multiset 自动按从小到大进行排序,因此一段定长区间的最大值即为 *s.rbegin()
。
2.1.3 代码
multiset<int,greater<int> > s; //从大到小排序,不去重
inline void Multiset(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&x[i]);//input