标签:情况 class empty 严格 continue 存在 swa rip lower
观察可以发现,子序列长度只能为3或4.
我们考虑4的情况,3的类似处理。
对于一个长度为4的序列a,b,c,d,如果满足max(a,d)<max(b,c)且min(a,d)>min(b,c),也就是说4个数中的严格最大值和严格最小值在b,c位置上,那么此时这个序列就不存在长度为3的非严格递增或非严格递减子序列。
这样根据贪心的思想,我们对于每个位置r,我们预处理出最靠右边的位置l,使得存在l,x1,x2,r成为长度为4的满足条件的序列。
我们假设\(lmin_i,lmax_i,rmin_i,rmax_i\)分别表示左边第一个比\(a_i\)小的和大的位置,右边第一个比\(a_i\)小的和大的位置。
那么每一对a,d,我们只要\(a < lmax_d\)且\(rmax_a<d\),那么我们取两个之中大的一个就可以保证大于a和d了。最小值同理取得。
#include <bits/stdc++.h>
#define pb emplace_back
using namespace std;
const int maxn = 2e5;
int a[maxn + 11],lmin[maxn + 11],lmax[maxn + 11],rmin[maxn + 11],rmax[maxn + 11];
int ans3[maxn + 11][5],ans4[maxn + 11][5];
set <int> :: iterator it;
vector <int> v[maxn + 11];
int main(){
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n,q; cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
stack <int> s;
// lmin
for (int i = 1; i <= n; i++) {
while (!s.empty() && a[s.top()] >= a[i]) s.pop();
if (s.empty()) lmin[i] = 0; else lmin[i] = s.top();
s.push(i);
}
// lmax
while (!s.empty()) s.pop();
for (int i = 1; i <= n; i++) {
while (!s.empty() && a[s.top()] <= a[i]) s.pop();
if (s.empty()) lmax[i] = 0; else lmax[i] = s.top();
s.push(i);
}
// rmin
while (!s.empty()) s.pop();
for (int i = n; i >= 1; i--) {
while (!s.empty() && a[s.top()] >= a[i]) s.pop();
if (s.empty()) rmin[i] = n + 1; else rmin[i] = s.top();
s.push(i);
}
// rmax
while (!s.empty()) s.pop();
for (int i = n; i >= 1; i--) {
while (!s.empty() && a[s.top()] <= a[i]) s.pop();
if (s.empty()) rmax[i] = n + 1; else rmax[i] = s.top();
s.push(i);
}
for (int i = 1; i <= n;i++) {
int pos = max(rmin[i] , rmax[i]);
if (pos <= n) v[pos].pb(i);
}
set <int> lef;
lef.insert(n + 1);
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 4; j++) ans4[i][j] = ans4[i - 1][j];
for (auto pos : v[i]) lef.insert(pos); v[i].clear();
int pos = min(lmin[i] , lmax[i]);
it = lef.lower_bound(pos);
if (it == lef.begin()) continue;
it--; int x1 = *it;
if (ans4[i][0] && x1 <= ans4[i][0]) continue;
int x2 = a[rmax[x1]] > a[lmax[i]] ? rmax[x1] : lmax[i];
int x3 = a[rmin[x1]] < a[lmin[i]] ? rmin[x1] : lmin[i];
if (x2 > x3) swap(x2 , x3);
ans4[i][0] = x1; ans4[i][1] = x2; ans4[i][2] = x3; ans4[i][3] = i;
}
lef.clear();
for (int i = 1; i <= n; i++)
if (rmax[i] <= n) v[rmax[i]].pb(i);
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 3; j++) ans3[i][j] = ans3[i - 1][j];
for (auto pos : v[i]) lef.insert(pos); v[i].clear();
int pos = lmax[i];
it = lef.lower_bound(pos);
if (it == lef.begin()) continue;
it--;
int x1 = *it;
int x2 = a[rmax[x1]] > a[lmax[i]] ? rmax[x1] : lmax[i];
ans3[i][0] = x1; ans3[i][1] = x2; ans3[i][2] = i;
}
lef.clear();
for (int i = 1; i <= n; i++)
if (rmin[i] <= n) v[rmin[i]].pb(i);
for (int i = 1; i <= n; i++) {
if (ans3[i - 1][0] > ans3[i][0]) {
for (int j = 0; j < 3; j++) ans3[i][j] = ans3[i - 1][j];
}
for (auto pos : v[i]) lef.insert(pos); v[i].clear();
int pos = lmin[i];
it = lef.lower_bound(pos);
if (it == lef.begin()) continue;
it--;
int x1 = *it;
int x2 = a[rmin[x1]] < a[lmin[i]] ? rmin[x1] : lmin[i];
if (x1 > ans3[i][0]){
ans3[i][0] = x1; ans3[i][1] = x2; ans3[i][2] = i;
}
}
while (q--) {
int l,r; cin >> l >> r;
if (ans4[r][0] >= l) {
puts("4");
for (int i = 0; i < 4; i++) printf("%d " , ans4[r][i]);
puts("");
}
else if (ans3[r][0] >= l) {
puts("3");
for (int i = 0; i < 3; i++) printf("%d " , ans3[r][i]);
puts("");
}
else puts("0");
}
}
Codeforces Round #630 -- G. No Monotone Triples
标签:情况 class empty 严格 continue 存在 swa rip lower
原文地址:https://www.cnblogs.com/Embiid/p/12623316.html