思路
LIS 是一个非常经典的 DP 问题
一般做法, 状态转移方程为
显然, 这样做的时间复杂度为 \(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;
}