序列最大值查询

这题需要找一个跨度最小的排序后相邻两个数差值为 且长度为 的子序列,但是由于子序列不一定是连续的,因此从下标入手很难做出来。不如换个思路:从值入手。

表示 在原数组当中的下标,那么 便是任意满足条件的子序列当中每一个数的下标。因此,我们只需要计算对于每一个 当中最大值与最小值的差值就行了。

看到很多人都为了求区间最值而写了线段树和 ST 表,实际上只需要使用 set 就行了,代码极短。时间复杂度:

#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;
}