题目连接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1134html
第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
输出最长递增子序列的长度。
8 5 1 6 8 2 4 5 10
5
一开始我是用dp写的,原本觉得就是一道模板题,发现超时了,时间复杂度是o(n2),先贴下超时的代码
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int a[50005],dp[50005]; int main() { int n,ans=0; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) { dp[i]=1; for(int j=0;j<i;j++) { if(a[i]>a[j]) dp[i]=max(dp[i],dp[j]+1); } ans=max(ans,dp[i]); } printf("%d\n",ans); return 0; }
以后看了博客才知道要用二分,这样时间复杂度就只有o(nlogn),要用len记录一下当前最长子序列的数量,这里用到了ios
二分查找的函数lower_bound(),这个函数有三个参数lower_bound(f,f+len,a[i]),f和f+len是指针,就是在f到f+len二分查找a[i]放置的位置,返回的也是指针,不会能够百度下。数组
代码:函数
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; int a[50005]; int f[50005]; int main() { int n,maxn; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); int len=1; memset(f,0,sizeof(f));//建立一个新数组存放最长上升序列 f[0]=a[0]; for(int i=1;i<n;i++) { int pos=lower_bound(f,f+len,a[i])-f;//二分查找i+1个数中最长上升序列,a[i]的位置 f[pos]=a[i]; /*cout<<ans<<" "<<pos<<endl;*/ len=max(len,pos+1);//最长上升序列的数量 } /*for(int i=0;i<ans;i++) cout<<f[i]<<endl;*/ printf("%d\n",len); return 0; }