探究最長不下降子序列

簡介

這是一個很初級的dp模型,最簡單的是O(n2)O(n^2)的,但是爲了時間快,我們有出現了O(n log n)的算法。在這裏予以講解。

講解

一、O(n2)O(n^2)

這個想必大家一定閉着眼睛都能打出來吧。
我們設f[i]表示取到第i個的最長子序列長度。
然後就可以N2N^2枚舉,暴力轉移:f[i]=max(f[i],f[j]+1);

二、O(n log n)

其實n log n只是換了一種方式去計算,而且比上面的更好理解,我們就可以形象的看到這個最長的長度是怎麼被堆積出來的。(但是實際上,這種算法我們是無法看到最終序列的,只能知道答案,然而我們可以知道只有前i個數時,必選i的最長長度)。
這個算法就是:
①每次加入一個數,顯然,如果這個序列頂的數比它要小,那麼就可以直接放進隊尾,並且長度加一。
②但是問題來了,如果比它要大,那麼就只能在中間找一個它能夠存放的地方。而這個地方剛好滿足左邊的小於等於它,右邊的大於等於它。於是我們就得到了必選這個時的最長長度爲找到的這個地方x。
那麼怎麼找呢?二分!因爲這是一個完全單調的隊列。
最終答案就是每次累加出來的長度。

#include<cstdio>
#include<iostream>
using namespace std;
int f[100005]int n,a[100005];
int main()
{
	scanf("%d",&n);
	int i,j,l,r,mid;
	for (i=1;i<=n;++i)
		scanf("%d",&a[i]);
	f[0]=0;
	for (i=1;i<=n;++i)
	{
		if(a[i]>f[f[0]])
			f[++f[0]]=a[i];
		else
		{
			l=1;r=f[0];
			while(l<r)
			{
				mid=(l+r)/2;
				if(f[mid]>a[i])r=mid;
				else l=mid+1;	
			}	
			f[l]=a[i];
		}
	}
	printf("%d\n",f[0]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章