zoukankan      html  css  js  c++  java
  • HDU6592 Beauty Of Unimodal Sequence

    Beauty Of Unimodal Sequence

    给一个序列,在满足单调递增或者单调递减或者先增后减的最长子序列集合里找到下标字典序最大以及最小的两个子序列,输出这两个子序列里元素的下标。

    n≤3×105

    moomhxy的题解

    先正着求一遍LIS,再反着求一遍LIS,求出每个点作为上升子序列结尾的最大长度和每个点作为下降子序列开头的最大长度。

    我们可以枚举这个单峰序列的峰顶是什么,这样最长长度就找到了。

    然后考虑怎么构造解。

    求字典序最小的话,首先找到第一个顶峰,然后往前找递减的序列中下标较小的,往后就依次找,这样能保证字典序最小。

    如何找这个下标较小的呢?显然我们希望每种结尾长度的点都越靠前越好。所以用单调栈维护即可。

    最大的话找到最后一个顶峰,往前是依次找,往后是找LIS中下标大的。维护方法类似。

    时间复杂度 O(n log n),瓶颈在于求LIS。

    CO int N=300000+10;
    int a[N],dp[N],up[N],down[N];
    int h[N],st[N],ans[N];
    
    void real_main(int n){
    	fill(dp,dp+n+1,INT_MAX),dp[0]=0;
    	for(int i=1;i<=n;++i){
    		read(a[i]);
    		up[i]=lower_bound(dp+1,dp+n+1,a[i])-dp;
    		dp[up[i]]=a[i];
    	}
    	fill(dp,dp+n+1,INT_MAX),dp[0]=0;
    	for(int i=n;i;--i){
    		down[i]=lower_bound(dp+1,dp+n+1,a[i])-dp;
    		dp[down[i]]=a[i];
    	}
    	// minimum lexicographic order
    	int tot=0;
    	int peak=1,height=up[1]+down[1];
    	for(int i=2;i<=n;++i)
    		if(up[i]+down[i]>height) peak=i,height=up[i]+down[i];
    	int top=0;
    	h[up[peak]]=a[peak];
    	for(int i=peak-1;i;--i){
    		if(a[i]>=h[up[i]+1]) continue;
    		while(top and up[i]>=up[st[top]]) --top;
    		st[++top]=i;
    		h[up[i]]=a[i];
    	}
    	for(;top;--top) ans[++tot]=st[top];
    	ans[++tot]=peak;
    	for(int i=peak+1;i<=n;++i)
    		if(down[i]==down[ans[tot]]-1 and a[i]<a[ans[tot]]) ans[++tot]=i;
    	for(int i=1;i<=tot;++i) printf("%d%c",ans[i]," 
    "[i==tot]);
    	// maximum lexcographic order
    	tot=0;
    	peak=1,height=up[1]+down[1];
    	for(int i=2;i<=n;++i)
    		if(up[i]+down[i]>=height) peak=i,height=up[i]+down[i];
    	top=0;
    	st[++top]=peak;
    	for(int i=peak-1;i;--i)
    		if(up[i]==up[st[top]]-1 and a[i]<a[st[top]]) st[++top]=i;
    	for(;top;--top) ans[++tot]=st[top];
    	h[down[peak]]=a[peak];
    	for(int i=peak+1;i<=n;++i){
    		if(a[i]>=h[down[i]+1]) continue;
    		while(tot and down[i]>=down[ans[tot]]) --tot;
    		ans[++tot]=i;
    		h[down[i]]=a[i];
    	}
    	for(int i=1;i<=tot;++i) printf("%d%c",ans[i]," 
    "[i==tot]);
    }
    int main(){
    	for(int n;~scanf("%d",&n);) real_main(n);
    	return 0;
    }
    

    HDU什么时候开始支持<bits/stdc++.h>了……

  • 相关阅读:
    AWS的EC2实例搭建服务器使用stackoverflow教程
    亚马逊云开服之旅
    Linux主机之间ssh免密登录配置方法
    阿里云运维培训讲解
    区块链技术在物流领域应用分析
    公众号页面分享朋友圈后点击跳转到小程序的方法介绍
    数据库主库从库宕机重启后binlog数据同步
    Docker+ElasticSearch+Logstash+Kibana+Filebeat搭建方法
    linux实现磁盘自动挂载脚本
    阿里云ecs基于镜像进行旧服务器迁移到新服务器
  • 原文地址:https://www.cnblogs.com/autoint/p/11729178.html
Copyright © 2011-2022 走看看