最长上升子序列(LIS)的求法
生活随笔
收集整理的這篇文章主要介紹了
最长上升子序列(LIS)的求法
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最長上升子序列(LIS)
給定一個(gè)長度為N的序列A
滿足:
1. 1<=x1< x2< x3<…xk<=N
2. A[x1] < A[x2] < A[x3] < … < A[xk]
即尋找一個(gè)最長子序列,滿足該子序列中每個(gè)元素嚴(yán)格遞增(其實(shí)不嚴(yán)格遞增也可以做)
做最長上升子序列有兩種方法:
1.動(dòng)態(tài)規(guī)劃(O(n2))
dp[i]表示取到第i個(gè)數(shù)的最長上升子序列
若有j滿足a[j] < a[i]
dp[i]=max(dp[j])+1
否則dp[i]=1
直接貼代碼
2.貪心?(O(nlogn))
用一個(gè)棧維護(hù)最長上升子序列的第i個(gè)元素的最小值,顯然這個(gè)最小值是單調(diào)不減的,進(jìn)來一個(gè)數(shù),如果比棧頂打就壓入棧,否則二分更新棧內(nèi)元素
易懂代碼
經(jīng)過優(yōu)化的代碼,適合做板子(注意理解)
#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; }總結(jié)
以上是生活随笔為你收集整理的最长上升子序列(LIS)的求法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 整数判重、大整数Hash
- 下一篇: NOIP2017提高组比赛总结