單調遞增子序列(二)(南陽oj214)
阿新 • • 發佈:2019-02-08
單調遞增子序列(二)
時間限制: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型整數)! - 輸出
- 對於每組測試資料輸出整形數列的最長遞增子序列的長度,每個輸出佔一行。
- 樣例輸入
-
7 1 9 10 5 11 2 13 2 2 -1
- 樣例輸出
-
5 1
- 來源
- 上傳者
經典程式碼超時,複雜度(n*n)。
二分查詢,複雜度n(logn)可以飄過!#include<stdio.h> #include<algorithm> using namespace std; int a[100010]; int dp[100010]; int main() { int i,j,n; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) { scanf("%d",&a[i]); dp[i]=1; } for(i=n-2;i>=0;i--) { for(j=i+1;j<n;j++) { if(a[i]<a[j]&&dp[i]<dp[j]+1) dp[i]=dp[j]+1; } } sort(dp,dp+n); printf("%d\n",dp[n-1]); } return 0; }
#include<stdio.h> #include<string.h> int a[100010]; int s[100010]; int len,i; int search(int i) { int left=1,right=len; while(left<right) { int mid=(left+right)/2; if(s[mid]>a[i]) right=mid; else if(s[mid]==a[i]) return mid; else left=mid+1; } return left; } int main() { int j,n; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) scanf("%d",&a[i]); len=1; s[len]=a[1]; for(i=2;i<=n;i++) { if(a[i]>s[len]) { len++; s[len]=a[i]; } else { j=search(i); s[j]=a[i]; } } printf("%d\n",len); } return 0; }