f[i]代表当前长度为i的上升子序列的最小结尾
以len记录当前最长上升子序列长度
DP分类讨论(1.维护最大长度 2.维护最小结尾)
1.当前元素a[i]>f[len],更新len及f[len+1]
2.否则,在f中寻找下界为a[i](>=此元素)的位置pos,此时f[0~pos-1]都<a[i],a[i]将处于长度为(pos-1)+1的上升子序列的结尾,于是更新f[pos]为a[i],维护最小结尾.
lower_bound(a+l,a+r+1,x)-a 指在a[l,r]中找到下界为x的位置
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> #include <set> #define ll long long using namespace std; const int MAXN=1e6+10; int n,len; int f[MAXN],a[MAXN]; inline int in() { int x=0,flag=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') flag=-1;ch=getchar();} while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*flag; } int main() { n=in(); for (int i=1;i<=n;i++) a[i]=in(); len=1; f[1]=a[1]; for (int i=2;i<=n;i++) { if (a[i]>f[len]) f[++len]=a[i]; else { /* int l=1,r=len,mid=0,pos=0; while (l<=r) { mid=(l+r)/2; if (f[mid]<a[i]) l=mid+1; else pos=mid,r=mid-1; } */ int pos=lower_bound(f+1,f+len+1,a[i])-f; f[pos]=a[i]; } } printf("%d",len); return 0; }