題目連接: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; }