最长上升子序列(LIS)的求法
生活随笔
收集整理的這篇文章主要介紹了
最长上升子序列(LIS)的求法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最長上升子序列(LIS)
給定一個長度為N的序列A
滿足:
1. 1<=x1< x2< x3<…xk<=N
2. A[x1] < A[x2] < A[x3] < … < A[xk]
即尋找一個最長子序列,滿足該子序列中每個元素嚴格遞增(其實不嚴格遞增也可以做)
做最長上升子序列有兩種方法:
1.動態規劃(O(n2))
dp[i]表示取到第i個數的最長上升子序列
若有j滿足a[j] < a[i]
dp[i]=max(dp[j])+1
否則dp[i]=1
直接貼代碼
2.貪心?(O(nlogn))
用一個棧維護最長上升子序列的第i個元素的最小值,顯然這個最小值是單調不減的,進來一個數,如果比棧頂打就壓入棧,否則二分更新棧內元素
易懂代碼
經過優化的代碼,適合做板子(注意理解)
#include<cstdio> typedef long long LL; template <typename T> inline T max(const T a,const T b){return a>b?a:b;} template <typename T> inline T min(const T a,const T b){return a<b?a:b;} template <typename T> inline T abs(const T a){return a>0?a:-a;} template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;} template <typename T> inline LL log2(T x){register LL res=0;while(x>=2)x=x>>1,res++;return res;} template <typename T> inline T gcd(const T a,const T b){if(a%b==0)return b;return gcd(b,a%b);} template <typename T> inline void read(T&x) {char cu=getchar();x=0;bool fla=0;while(cu<'0'||cu>'9'){if(cu=='-')fla=1;cu=getchar();}while('0'<=cu&&cu<='9')x=x*10+cu-'0',cu=getchar();if(fla)x=-x; } template <typename T> void printe(const T x) {if(x>=10)printe(x/10);putchar(x%10+'0'); } template <typename T> inline void print(const T x) {if(x<0)putchar('-'),printe(-x);else printe(x); } LL N,a[100001],len,num; inline LL search(const LL x) {register LL l=1,r=len,ans=0;while(l<=r){register LL mid=(l+r)>>1;if(a[mid]>=x)ans=mid,r=mid-1;else l=mid+1;}return ans; } int main() {read(N);for(register LL i=1;i<=N;i++){read(num);if(!len||num>a[len])a[++len]=num;else a[search(num)]=num;}print(len);return 0; }總結
以上是生活随笔為你收集整理的最长上升子序列(LIS)的求法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 整数判重、大整数Hash
- 下一篇: NOIP2017提高组比赛总结