NYOJ 题目214 单调递增子序列(二)(动态规划,二分)

来源:互联网 发布:徐州淘宝产业链 编辑:程序博客网 时间:2024/06/05 10:01


奋斗!!!!!

单调递增子序列(二)

时间限制:1000 ms  |  内存限制:65535 KB
难度:4
描述

给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。

如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。

输入
有多组测试数据(<=7)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
数据以EOF结束 。
输入数据保证合法(全为int型整数)!
输出
对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
样例输入
71 9 10 5 11 2 1322 -1
样例输出
51
来源
[521521]改编
上传者
ACM_赵铭浩

思路:http://blog.csdn.net/xuezhongfenfei/article/details/9191029

对于这道题传统的求最长递增子数列是肯定会超时的,所以我们要换一种思路,可以用数组维护一个递增数列a[n],其中a[i]代表的是可以长度为i的队列中最小的数。
那么我们可以这样维护队列:按照数的输入顺序依次加入队列,如果该数大于队列中最大的数则将其加入到队列尾部;如果不大于,我们可以换一种思路想(我个人感觉可以想是贪心),对于一个递增队列,我们想使他尽可能的长,那么我们就应该选使队列中的数尽可能的小,比如1,3,5,7,9和1,2,3,4,5都是一个长度为5的递增数列,但是为了使得数列的长度尽可能的长我们应该选择后者,因为再来一个数6,我们可以加在1,2,3,4,5的后面使得数列的长度变为6,而对于1,3,5,7,9则长度不可能增加,所以如果添加的数不大于队列中最大的数,那我们应该扫描队列,使得该数替换队列中第一个比它大的数,使得队列中的数更小些,然后到最后,输出数列的长度就是队列的结果,下面是代码:

ac代码

#include<stdio.h>#include<string.h>int dp[100005];int main(){int n;while(scanf("%d",&n)!=EOF){int x,len=0,i;scanf("%d",&x);dp[++len]=x;for(i=2;i<=n;i++){scanf("%d",&x);if(x>dp[len])dp[++len]=x;else{int l=1,r=len;while(l<=r){int mid=(l+r)/2;if(dp[mid]>x)r=mid-1;elsel=mid+1;}dp[l]=x;}}printf("%d\n",len);}}


1 0
原创粉丝点击