码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #630 -- G. No Monotone Triples

时间:2020-04-02 22:19:46      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:情况   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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!