2023-6-19

B. Approximating a Constant Range

题意:
给你一个数组 \(a\) ,数组满足 \(|a_i-a_{i-1}\leq 1|\),问你数组中最长的连续子序列是多少,连续子序列需要满足 \(max-min \leq 1\)

数据范围:
\(1\leq n \leq 10^5,1\leq a_i \leq 10^5\)


\(Tutorial:\)

\(max-min \leq 1\) \(<=>\) \([l,r]\) 中最多只有 \(2\) 种不同的数,问题就变成了经典的双指针问题

这里可以扩展一下,若没有题目所说的性质,只是一个普通的数组 \(a\),且要求 \(max-min\leq k\) ,同样我们也可以利用
双指针维护,这里可以用单调队列,\(ST\) 表, \(multiset\) 维护区间最值。

\(case:\)

\([l,r]\) 中是满足 \(max-min <= k\),那么对于 \(l'> l\)\([l',r]\) 一样是满足条件的
\([l,r]\) 中是满足 \(max-min >= k\),那么对于 \(r'> r\)\([l,r']\) 一样是满足条件的


本题的 \(Code:\)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N], st[N];

int main () {
    
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }

    int ans = 0, sz = 0;
    for (int i = 1, j = 1; i <= n; i++) {
        if (++st[a[i]] == 1) sz++;
        while (j <= n && sz > 2) {
            if (--st[a[j++]] == 0) sz--;
        }
        ans = max(ans, i - j + 1);
    }
    cout << ans << '\n';
    
    return 0;
}

扩展的 \(Code:\) (用 \(multiset+\) 双指针维护)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N], st[N];

int main () {
    
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }

    multiset<int> se;
    int ans = 0;
    for (int i = 1, j = 1; i <= n; i++) {
        se.insert(a[i]);
        while(j <= n && *se.rbegin() - *se.begin() > 1) {
            se.erase(se.find(a[j++]));
        }
        ans = max (ans, i - j + 1);
    }
    cout << ans << '\n';
    
    return 0;
}
posted @ 2023-06-19 17:13  jackle  阅读(3)  评论(0编辑  收藏  举报