題目描述
給定一個長度為n的整數序列S,求這個序列中最長的嚴格遞增子序列的長度。
輸入描述:
第一行,一個整數n (2<=n<=50000),表示序列的長度
第二行,有n個整數 (-10^9 <= S[i] <= 10^9),表示這個序列
輸出描述:
輸出一個整數,表示最長遞增子序列的長度
輸入
6
4 0 5 8 7 8
輸出
4
備注:
樣例解釋 子序列為 0 5 7 8
思路:這題是最長上升子序列模板題,有兩種寫法,但是 o(n^2)被卡了,會超時,應該用二分搜索,時間復雜度 o(nlogn)......
o(n^2)寫法:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 using namespace std; 10 #define ll long long
11 const int maxn=5e4+5; 12 int dp[maxn]; 13 int num[maxn]; 14 int main() 15 { 16 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 17 memset(dp,0,sizeof(dp)); 18 int n; 19 cin>>n; 20 for(int i=1;i<=n;i++) 21 cin>>num[i]; 22 int ans=-1; 23 for(int i=1;i<=n;i++) 24 { 25 dp[i]=max(dp[i],1);//最短起碼為1
26 for(int j=i+1;j<=n;j++) 27 { 28 if(num[j]>=num[i])//連續
29 dp[j]=max(dp[j],dp[i]+1);//刷新dp[j]
30 } 31 ans=max(ans,dp[i]);//找最長上升子序列長度
32 } 33 cout<<ans<<endl; 34 return 0; 35 }
o(nlogn)寫法:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 using namespace std; 10 #define ll long long
11 const int maxn=5e4+5; 12 const int inf=1e9+7; 13 //最長上升子序列
14 int dp[maxn]; 15 int num[maxn]; 16 int main() 17 { 18 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 19
20 int n; 21 cin>>n; 22
23 for(int i=0;i<n;i++) 24 cin>>num[i]; 25
26 fill(dp,dp+n,inf); 27
28 for(int i=0;i<n;i++) 29 *lower_bound(dp,dp+n,num[i])=num[i]; 30
31 cout<<lower_bound(dp,dp+n,inf)-dp<<endl; 32
33 return 0; 34 }