最长上升子序列
-
简单DP
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=2e5+10; int a[maxn]; int dp[maxn]; int main() { int n,i,t; cin>>n; for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) dp[i]=1; for(i=1;i<=n;i++) for(t=1;t<i;t++) if(a[i]>a[t]) dp[i]=max(dp[i],dp[t]+1); int maxi=0; for(i=1;i<=n;i++) maxi=max(dp[i],maxi); cout<<maxi<<endl; } // 时间复杂度 O(n*n)
-
栈的优化 O(n*logn )
模拟单调数组,当下一个数大于当前最大数时,插入该数;当下一个数小于当前数时,则二分查找第一个不小于该数的数,则替换之,此时不改变总最长子序列长度,且减少了序列中的值,使之能达到更大长度。
数组的长度即为最长上升子序列的长度
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=2e5+10; int a[maxn]; int s[maxn]; int main() { int n,i,t,num=0; cin>>n; for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) { if(a[i]>s[num]) s[++num]=a[i]; else{ int l=1,r=num; while(l<r) { int mid=(l+r)/2; if(s[mid]<=a[i]) l=mid+1; else r=mid; } s[l]=a[i]; } } cout<<num<<endl; }