思路

LIS 是一个非常经典的 DP 问题
一般做法, 状态转移方程为

\[F[i]=\max_{0 \leq j < k, A[j]<A[i]} \{F[j]+1\} \]

显然, 这样做的时间复杂度为 \(O(n^2)\)
但还有一种二分做法可以使时间复杂度降到 \(O(n\log n)\)
具体讲解可以见这道题 P1020 [NOIP1999 普及组] 导弹拦截

蒟蒻代码

// LIS 最长上升子序列
#include <bits/stdc++.h>
#define re register
using namespace std;

const int N=1e5+5;
int n;
int a[N];

int len=0;
int lis[N];

int main()
{
    ios::sync_with_stdio(0);
    clock_t c1 = clock();
#ifdef LOCAL
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
#endif
    // ======================================================================
    cin>>n;
    for(re int i=1;i<=n;i++) cin>>a[i];
    for(re int i=1;i<=n;i++){
        // 不允许有相等的
        if(a[i]>lis[len] || len==0) lis[++len]=a[i];    // 直接接上去
        else{
            int p=lower_bound(lis+1,lis+1+len,a[i])-lis;
            lis[p]=a[i];
        }
    }
    cout<<len<<endl;
    // ======================================================================
end:
    cerr << "Time Used:" << clock() - c1 << "ms" << endl;
    return 0;
}