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