hdu 6592 Beauty Of Unimodal Sequence (LIS + 单调栈)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6592

先分别正着反着求一遍 \(LIS\)
可以证明,字典序最小的单峰序列,一定是先找到最左边的峰点,向左单调栈维护每一个长度的最左边的位置,向右贪心
最大字典序同理

维护单调栈时要注意元素大小的单调性

注意输出不能有行末空格

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const int maxn = 300010;

int n, inf;
int a[maxn], b[maxn], f[maxn], g[maxn];
int c[maxn], d[maxn], t[maxn], p[maxn];
int ans1[maxn], ans2[maxn];
int sta[maxn], top;

bool check1(P x, P y){
	if(x.first == y.first){
		return x.second > y.second;
	}
	return x.first < y.first;
}

bool check2(P x, P y){
	if(x.first == y.first){
		return x.second < y.second;
	}
	return x.first < y.first;
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	while(scanf("%d", &n) != EOF){
		memset(f, 0x3f, sizeof(f));
		memset(g, 0x3f, sizeof(g));
		inf = f[0];
		memset(c, 0, sizeof(c));
		memset(d, 0, sizeof(d));
		memset(p, 0, sizeof(p));
		for(int i = 1 ; i <= n ; ++i) scanf("%d", &a[i]);
		
		for(int i = 1 ; i <= n ; ++i){
			int pos = lower_bound(f + 1, f + 1 + n, a[i]) - f;
			f[pos] = a[i];
			c[i] = pos;
		}
		
		for(int i = n ; i >= 1 ; --i){
			int pos = lower_bound(g + 1, g + 1 + n, a[i]) - g;
			g[pos] = a[i];
			d[i] = pos;
		}
			
		int sp = 1, bp = n;
		int m = c[1] + d[1];
		for(int i = 2 ; i <= n ; ++i){
			if(c[i] + d[i] > m){
				m = c[i] + d[i];
				sp = i;
			}
		}
	
		m = c[n] + d[n];
		for(int i = n - 1 ; i >= 1 ; --i){
			if(c[i] + d[i] > m) {
				m = c[i] + d[i];
				bp = i;
			}
		}
		
		top = 0; p[c[sp]] = a[sp];
		for(int i = sp - 1 ; i >= 1 ; --i){
			if(a[i] >= p[c[i] + 1]) continue;
			while(c[sta[top]] <= c[i] && top >= 1) --top;
			sta[++top] = i;
			p[c[i]] = a[i];
		}
		int num = 0;
		for(int i = top ; i >= 1 ; --i){
			ans1[++num] = sta[i];
		}
	
		ans1[++num] = sp;
		int cnt = 0;
		int las = sp;
		for(int i = sp + 1 ; i <= n ; ++i){
			if(a[i] >= a[las]) continue;
			if(d[i] == d[las] - 1){
				t[++cnt] = i;
				las = i;
			}
		}
		
		for(int i = 1 ; i <= cnt ; ++i){
			ans1[++num] = t[i];
		}
		for(int i = 1 ; i <= num ; ++i){
			printf("%d", ans1[i]);
			if(i != num) printf(" ");
		}
		printf("\n");
		
		memset(p, 0, sizeof(p));
		p[d[bp]] = a[bp];
		top = 0;
		for(int i = bp + 1 ; i <= n ; ++i){
			if(a[i] >= p[d[i] + 1]) continue;
			while(d[sta[top]] <= d[i] && top >= 1) --top;
			sta[++top] = i;
			p[d[i]] = a[i];
		}
	
		cnt = 0;

		las = bp;
		for(int i = bp - 1 ; i >= 1 ; --i){
			if(a[i] >= a[las]) continue;
			if(c[i] == c[las] - 1){
				t[++cnt] = i;
				las = i;
			}
		}
		num = 0;
		for(int i = cnt ; i >= 1 ; --i) {
			ans2[++num] = t[i];
		}
		ans2[++num] = bp;
		for(int i = 1 ; i <= top ; ++i){
			ans2[++num] = sta[i];
		}
		for(int i = 1 ; i <= num ; ++i){
			printf("%d", ans2[i]);
			if(i != num) printf(" ");
		}
		printf("\n");
	}
	return 0;
}
posted @ 2020-12-24 20:45  Tartarus_li  阅读(75)  评论(0编辑  收藏  举报