zoukankan      html  css  js  c++  java
  • 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("
    ");
    		
    		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("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    怎样的配色能让你的作品高端!上档次呢?
    响应式布局的9项基本原则
    SOHO设计师如何保障自己的权益
    加载动态设计--等待的艺术创作思维
    初学者所必备的设计类网站
    网页设计师该向印刷设计学习的3个规则
    [并发编程] -- 内存模型(针对JSR-133内存模型)篇
    [并发编程] -- 线程池篇
    [并发编程] -- 容器和框架篇
    [并发编程] -- 工具类篇
  • 原文地址:https://www.cnblogs.com/tuchen/p/14186337.html
Copyright © 2011-2022 走看看