单调递增子序列(二)
时间限制: 1000ms
内存限制: 128000KB
64位整型: Java 类名:
题目描述
给定一整型数列{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型整数)!
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
数据以EOF结束 。
输入数据保证合法(全为int型整数)!
输出
对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
样例输入
7 1 9 10 5 11 2 13 2 2 -1
样例输出
5 1
来源
分类
思路:这都属于求最长递增子序列的问题,例如ss[i],{1,9,10,2,5,6,25,11,}。这组数,先定义一个dp[ i ]数组,dp[1]=ss[1]=1;然后把每一个ss[i],在dp数组中进行二分查找,如ss[2]=9,查找返回2,则dp[2]=9, ss[3]=10查找的dp[3]=10,ss[4]二分查找返回2,则dp[2]=2,重复上述操作得dp[3]=5,dp[4]=6;dp[5]=25,dp[5]=11,用一个count记录最大的,输出count即可。代码如下:
#include<stdio.h>
#include<string.h>
int dp[100010];
int a[100100];
int n;
int F(int m,int len)
{
int begin=1,end=len,mid;
while(begin<=end)
{
mid=(begin+end)/2;
if(m>dp[mid])
{
begin=mid+1;
}
else if(m<dp[mid])
{
end=mid-1;
}
else return mid;
}
return begin;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
dp[0]=-99999999;
dp[1]=a[1];
int sum=1;
for(int i=2; i<=n; i++)
{
int k=F(a[i],sum);
dp[k]=a[i];
if(k>sum)
sum=k;
}
printf("%d\n",sum);
}
return 0;
}