1. 程式人生 > 實用技巧 >【nlogn 模板】 最長上升子序列

【nlogn 模板】 最長上升子序列

傳送門

題意

給定一個序列求最長上升子序列,需要用\(O(n·logn)\)複雜度的做法

資料範圍

\(1\leq N\leq 10^{5}\)

題解

記錄最長的上升子序列長度,\(f[i]\)記錄長度為\(i\)的最長上升子序列的結尾數值,
\(f\)的數值一定是單調上升的,證明:
如果長度為\(x\)的結尾數值大於長度為\(x+1\)的,那麼\(x\)結尾的一定能夠接到\(x+1\)後面,更優顯然矛盾

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define ll long long
const int N=1e5+10;
int n;
int a[N],f[N];
int main(){
    scanf("%d",&n);
    rep(i,0,n) scanf("%d",&a[i]);

    int len=0;
    f[0]=-2e9;
    rep(i,0,n){
        int l=0,r=len;
        while(l<r){
            int mid=(l+r+1)>>1;
            if(f[mid]<a[i]) l=mid;
            else r=mid-1;
        }
        len=max(len,r+1);
        f[r+1]=a[i];
    }
    printf("%d\n",len);
}