Codeforces Round #630 -- G. No Monotone Triples

Posted embiid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #630 -- G. No Monotone Triples相关的知识,希望对你有一定的参考价值。

解法

观察可以发现,子序列长度只能为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的主要内容,如果未能解决你的问题,请参考以下文章

codeforces630C

codeforces 630H (组合数学)

codeforces 630 I(规律&&组合)

codeforces 630K - Indivisibility

codeforces 630C - Lucky Numbers 递推思路

Codeforces Global Round 19