nlogn求最長不上升子序列


這種問題一般都比較熟悉,我們先看n^2的算法

導彈攔截

時間限制: 1 Sec  內存限制: 128 MB
提交: 106  解決: 61
[提交][狀態][討論版]

題目描述

某國為了防御敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意 的高度,但是以后每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的導彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所 有的導彈。
輸入導彈一次飛來的高度(雷達給出的高度不大於30000的正整數)。計算這套系統最多能攔截多少導彈。

輸入

n顆依次飛來的導彈高度,導彈顆數<=1000。

輸出

一套系統最多攔截的導彈數。

樣例輸入

7 300 250 275 252 200 138 245

樣例輸出

5
令f[i]表示前i個數的最長序列長度f[j]=max(f[j],f[i]+1)i<j且a[i]>=a[j]
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[1005],f[1005],ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        f[i]=1;
        for(int j=1;j<i;j++)
        if(a[j]>=a[i])f[i]=max(f[i],f[j]+1);
    }
    for(int i=1;i<=n;i++)
    ans=max(ans,f[i]);
    cout<<ans<<endl; 
 } 

但是在一些n=100000的題目上O(n^2)的算法會時間超限。我們考慮優化這一算法。令B[i]=長度位i的序列最后一個一個字符的最大值。

對於新進來的一個數,我們看其能否跟新B數組中的一個值。如何跟新一個值呢?二分查找。

#include<iostream>
#include<cstdio>
#include<algorithm> 
using namespace std;
int n,B[100005],a[100005],len;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    B[1]=-a[1],len=1;
    for(int i=2;i<=n;i++)
    {
        if(-a[i]>=B[len]) B[++len]=-a[i];
        else
        {
            int pos=upper_bound(B+1,B+len,-a[i])-B;
            B[pos]=-a[i];
        }
    }
    cout<<len<<endl;
}

就是很短的代碼實現了nlogn的類lis功能。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM