思路很清晰,扫的时候保存每一个长度最小的序列,更新的时候二分找就可以了。
/*
最长上升子序列的O(nlogn)的算法
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
const int maxn=50000+10;
int a[maxn];
int d[maxn];//长度为i的递增子序列最后一个值的最小值
int find_ans(int num,int len){
int low=1;
int high=len;
while(low<=high){
int mid=(low+high)>>1;
if(d[mid]==num)return mid;
else if(d[mid]>num)high=mid-1;
else low=mid+1;
}
return low;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
memset(d,0,sizeof(d));
d[1]=a[1];
int len=1;
for(int i=2;i<=n;i++){
if(a[i]>d[len]){
d[++len]=a[i];
}
else{
int j=find_ans(a[i],len);//二分寻找第一个大于它的下标
d[j]=a[i];
}
}
printf("%d\n",len);
return 0;
}
用lower_bound也可以。