如果用普通的做法,他的时间复杂度是O(n2)的用在这道题就是会超时的
那么就要想一想如何优化
我们用f[i]表示所有子序列长度为i的子序列它的末尾的最小值
然后遍历数列N,找到f[N]中小于它的最大值,也就是说也就是说数列N中的那个数是可以接到找到的那个数后面从而构成一个长度i+1的子序列,找f[N]中小于它的最大值,我们可以使用二分查找
二分查找的时间复杂度是logn的由于要遍历N次所以总的时间复杂度是nlogn的
#include<iostream>
using namespace std;
const int N=1e5+10;
int q[N],a[N];//目前f[i]表示的是子序列长度为i的末尾最小的值
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int ans=0;//记录目前的最长子序列长度
q[0]=-2e9;//用来修改长度为1的子序列的最小值,因为a数组中有负数所以要先初始化一下q[0]
for(int i=1;i<=n;i++)
{
int l=0,r=ans;
while(l<r)
{
int mid =(l+r+1)>>1;
if(q[mid]<a[i])l=mid;
else r=mid-1;
}
q[l+1]=a[i];
ans=max(ans,l+1);
}
cout<<ans<<endl;
return 0;
}