• 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");
    	}
    } 
    
    
  • 相关阅读:
    Mysql 免密码登录,修改密码及忘记密码操作
    CentOS 6.9 升级MySQL 5.6.36到5.7.18
    【转载】详解布隆过滤器的原理、使用场景和注意事项
    AssemblyVersion、AssemblyFileVersion、AssemblyInformationalVersion 区别
    为什么要有财务自由【转】
    CacheManager.Core
    雪花算法,生成分布式唯一ID
    监控
    什么是并行、并发, 两者的区别是什么
    Emit用法
  • 原文地址:https://www.cnblogs.com/Embiid/p/12623316.html
Copyright © 2020-2023  润新知