SWUN 1075 - CD8

 


CD8

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 118            测试通过 : 25

描述

Comiday成都同人祭,是由Comiday成都同人祭组织委员会举办,目前西南地区最大的非商业性、非盈利性同人展会,每年分夏季和冬季两次,参展社团多达百余,参展作品种类繁多,是西南地区同人动漫爱好者交流的盛会。

 

CD8要在成都新会展中心举行了,这同时也吸引了ACM众多宅男,YH就是爱好者之一。但是他不想一个人去通宵排队,所以他叫CH一同前往。这个时候CH正在为一道题目纠结。

 

由N个整数组成的数列,你可以一次性取出一些连续的数字(当然你也可以选择不取),要求的是剩下的数列中连续且严格递增的子序列的长度最长。

 

例如有这样的一个数列: 5,3,4,9,2,8,6,7,1,那么我们取出9,2,8,(连续的)后,得到的序列是 5,3,4,6,7,1,那么这个数列里面连续且递增的序列最长是3,4,6,7(也是连续的)。

 

YH和CH经过一个小时激烈的讨论以后,得到一个结论:不可搞!

 

你能帮助他们把这道题目解决,让他们顺利去CD8站个痛快吗?

输入

 输入有两行,第一行是一个整数N(0 < N <= 50000)。第二行包含N个整数,每个整数都在0 到100 之间。

输出

 输出能达到的最长长度。

样例输入

9
5  3  4  9  2  8  6  7  1

样例输出

4

题目来源

CJ


 

题目地址: http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1075

 

方法: 哈希 +  两个DP

 

应某人要求,写了题解~~

 

(特地写了个 "深奥" 的Code~~~,看懂不看懂,就不是我事儿了~)

 

先对变量进行解释:

                  n :表示有n个成员。

                  last :表示上一次输入的成员。

                  now :表示当前输入的成员。

                  rm : record_numbers ,用于哈希,rm[ i ] 表示以i成员为结尾的最大连续上升序列。

                  len : 第一个dp,表示以当前成员为结尾的,最大连续上升序列的长度。

                  flen : 第一个dp,表示以上一个成员为结尾的,最大连续上升序列的长度。

                  len2 : 第二个dp,表示以当前成员为结尾的,去除连续的一段序列之后,所能达到的最大连续上升序列。

                  flen2 : 第二个dp,表示以上一个成员为结尾的,去除连续的一段序列之后,所能达到的最大连续上升序列。

 

于是很好理解,如果 last<now ,那么 len = flen+1 ,否则 len =1。

 

然后比较之前得到的,以 now 结尾的最大连续上升序列的长度,如果现在这个上升序列长度更大,则替换。

 

接下去,则是从 1 到 now-1 之间,找到一个以 [比now小的数] 为结尾的最大上升序列,接在now前面。那么这时,我们所忽略的连续序列为最优的忽略。

 

同时,len2 就是 [之前最大上升序列的长度mx] + 1

 

现在就是第二个dp的判断了,如果 len2<=flen2 ,同时 last<now,那么就表示:now可以放在last后面,并且flen2+1>len2 。于是len2 = flen2+1

 

这就表示了,删除了一段连续序列之后,以当前成员为结尾,最大上升序列为 len2 。

 

于是用 res 来更新以每一个成员结尾的最大连续上升序列长度。

 

 = = 、  其实解释的很详细了,看过之后,Code应该懂了吧。

 

#include<cstdio>

int main(){
	int i,j,mx,n,res,now,last,len,flen,len2,flen2,rm[105]={0};
	scanf("%d",&n);
	for(res=0,last=flen=flen2=0,i=1;i<=n;last=now,flen=len,flen2=len2,i++){
		scanf("%d",&now);
		len=last<now?flen+1:1;
		rm[now]<len?rm[now]=len:0;
		for(mx=0,j=1;j<now;j++)
			mx<rm[j]?mx=rm[j]:0;
		len2=mx+1;
		flen2>=len2&&last<now?len2=flen2+1:0;
		res<len2?res=len2:0;
	}
	printf("%d\n",res);
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值