簡介
這是一個很初級的dp模型,最簡單的是的,但是爲了時間快,我們有出現了O(n log n)的算法。在這裏予以講解。
講解
一、
這個想必大家一定閉着眼睛都能打出來吧。
我們設f[i]表示取到第i個的最長子序列長度。
然後就可以枚舉,暴力轉移: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]);
}