tzoj 6315 求最长不下降序列

描述

设有由n(1≤n≤200)个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)若存在i1<i2<i3<…<ie且有b(i1)≤b(i2)≤…≤b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。 例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中13,16,18,19,21,22,63就是一个长度为7的不下降序列,同时也有7 ,9,16,18,19,21,22,63组成的长度为8的不下降序列。

输入

第一行为n, 第二行为用空格隔开的n个整数。

输出

第一行为输出最大个数; 第二行为max个整数形成的不下降序列,答案可能不唯一,输出一种就可以了,本题进行特殊评测。

样例输入

14

13 7 9 16 38 24 37 18 44 19 21 22 63 15

样例输出

8

7 9 16 18 19 21 22 63

一道较为典型的dp题 困扰我的还是输出每个数据(第二行) 先给出代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn] ;
int dp[maxn];///dp[i]在i前比a[i]小的个数
map<int,int> mp;///记录该数前一个数的下标
int n; 
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)dp[i]=1;
	int ans=1;
	int maxx=1;
	for(int i=2 ;i<=n ;++i ){
       	for(int j=i-1;j>=1;--j){
       		//cout<<"i: "<<i<<"j: "<<j<<"\n";
       		 if(a[j]<=a[i]){
       		 	if(dp[i]<dp[j]+1)
       		 	    {
       		 	    	mp[i]=j;
       		 	    	dp[i]=dp[j]+1;
						//cout<<i<<" "<<j<<endl;
       		 	    }
       		 	    if(dp[i]>ans){
       		 	    	
       		 	    	ans=dp[i];
       		            maxx=i;
						break;
					}
				}
		   }
	}
	//for(int i=1;i<=n;++i)cout<<dp[i]<<" ";
    cout<<ans<<"\n";
    stack<int> st;
    st.push(a[maxx]);
    int tmp=mp[maxx];
	while(tmp){
		st.push(a[tmp]);
		tmp=mp[tmp];
	} 
	bool flag=true;
	while(!st.empty()){
		if(flag)cout<<st.top();
		else cout<<" "<<st.top();
		st.pop();
		flag=false;
	}
	return 0;
}

该代码多用了栈,耗费了时间和空间 我觉得我的代码还可以再优化一下mp反向记录就行,然后找到第一个数字的下标,就不用遇到栈,或者直接反向读取数据,然后判断不上升序列就行

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务