已经知道最长上升子序列的n^2算法
DP[i]=Max(DP[j])+1 j<i&&str[j]<str[i]
下面介绍优化的算法
用一个Top标记记录当前最长的上升子序列。并用一个数组Num[]记录所有该下标长度的子序列组中,最大值最小的那个值
例如有序列 1 2 6 2 3 4 则Num[2]=2 Num[3]=3 Num[4]=4
实现方法:遍历序列,如果当前元素值大于Num[top]则Num[++top]=当前元素的值,否则在Num数组中二分查找第一个大于或等于该元素值的下标为tmp,则Num[tmp]=当前元素值
Num[1]=1,Num[2]=2.Num[3]=6,Num[2]=2, 此时元素值为3,二分得到tmp=3,则Num[3]=3
#include<stdio.h>
#define Max(a,b) (a<b?b:a)
int N;
int Num[100001];
int DP[100001];
int Tmp[100001];
int Top;
int Ans;
int BinSearch(int num){
int l=1,r=Top,m;
while(l<=r){
m=(l+r)>>1;
if(num>Tmp[m]) l=m+1;
else r=m-1;;
}
return r;
}
int main(){
int i,j;
while(~scanf("%d",&N)){
/* Ans=0; 请无视O(n^2) TLE的算法
for(i=0;i<N;i++)
scanf("%d",&Num[i]);
for(i=0;i<N;i++){
DP[i]=1;
for(j=i-1;j>=0;j--){
if(Num[i]>Num[j])
DP[i]=Max(DP[i],DP[j]+1);
}
}
for(i=0;i<N;i++)
Ans=Max(Ans,DP[i]);
printf("%d\n",Ans);
}
*/
/* O(NlogN) */
for(i=0;i<N;i++)
scanf("%d",&Num[i]);
Top=0;
for(i=0;i<N;i++){
if(Num[i]>Tmp[Top]||0==Top)
Tmp[++Top]=Num[i];
else
Tmp[BinSearch(Num[i])+1]=Num[i];
}
printf("%d\n",Top);
}
return 0;
}