#序列最大值查询
这题需要找一个跨度最小的排序后相邻两个数差值为 $1$ 且长度为 $K$ 的子序列,但是由于子序列不一定是连续的,因此从下标入手很难做出来。不如换个思路:从值入手。
令 $f_i$ 表示 $i$ 在原数组当中的下标,那么 $f_a\sim f_{a+k-1}$ 便是任意满足条件的子序列当中每一个数的下标。因此,我们只需要计算对于每一个 $a$,$f_a\sim f_{a+k-1}$ 当中最大值与最小值的差值就行了。
看到很多人都为了求区间最值而写了线段树和 ST 表,实际上只需要使用 set 就行了,代码极短。时间复杂度:$\mathcal O(n\log_2 n)$。
```cpp
#include <iostream>
#include <set>
using namespace std;
const int kMaxN = 2e5 + 5;
int f[kMaxN], n, k, ans = 1e9;
set<int> s;
int main() {
cin >> n >> k;
for (int i = 1, x; i <= n; i++) {
cin >> x;
f[x] = i;
}
for (int i = 1; i <= n; i++) { // 遍历
s.insert(f[i]); // 将这个元素的下标加入 set
if (i >= k) { // 如果已经塞了 k 个元素
ans = min(ans, *s.rbegin() - *s.begin()); // 计算最小差值
s.erase(f[i - k + 1]); // 删除最前面的那个数
}
}
cout << ans << '\n';
return 0;
}
```