你可以在O(N log K)的时间内解决这个问题,其中N是数组的大小。
首先请注意,如果我们解决最小值的问题,那么最大值的解决方案也是相同的,只需将原始数组元素乘以-1即可。
因此,为了解决这个问题,我们需要一个支持添加、删除、查找集合中第k个项目的数据结构,然后我们可以使用滑动窗口循环所有需要的区间,根据需要添加和删除项目。
实际上,有许多结构可以在O(log N)的时间内支持所有这些操作,例如线段树、最小/最大堆、顺序统计树(一种B树)和其他一些结构。
顺序统计树是一种二叉搜索树,除了插入、查找和删除之外,还支持两个附加操作:
Select(i) - 查找树中存储的第i个最小元素。
Rank(x) - 查找元素x在树中的排名,即其在树的元素排序列表中的索引。
当自平衡树用作基本数据结构时,这两个操作都是O(log n)的。
示例代码(使用g++编译器的C++,该编译器幸运地在库中具有顺序统计树)
#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<pair<int,int>,null_type,less<pair<int,int>>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;
int main()
{
int n,k,L;
cin>>n>>k>>L;
vector<int>A(n+1);
for(int i=0; i<n; i++)cin>>A[i];
ordered_set S;
for(int i=0; i<k; i++)
S.insert({A[i],i});
for(int i=k; i<=n; i++)
{
cout<<S.find_by_order(L-1)->first<<" ";
S.erase(S.find({A[i-k],i-k}));
S.insert({A[i],i});
}
}