因为该题序列长度为100000,故用常规dp方法会超时。O(N2)
这里用二分查找+贪心思想来解这道题。O(NLogN)
先建立一个数组b[]用来存放规定的最长单调子序列。
接下来遍历a数组。
1.如果a[i]大于b的末尾就直接添加在b的末尾。
2.如果a[i]小于b的末尾我们就找到b数组中最小的大于a[i]的那个数并替换它。这里用到了贪心思想。查找的方法用二分查找。
3.如果等于则不处理。
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
int a[maxn];
int b[maxn];
int BinarySearch(int* c,int n,int e){
int left=1;
int right=n;
int mid;
while(left<=right){
mid=(left+right)>>1;
if(c[mid]==e) return mid;
else if(c[mid]>e) right=mid-1;
else left=mid+1;
}
return left;
}
int main(){
int n;
while(cin>>n){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
cin>>a[i];
b[1]=a[1];
int k=1;
for(int i=2;i<=n;i++){
if(a[i]==b[k]) continue;
if(a[i]>b[k])
b[++k]=a[i];
else{
int w=BinarySearch(b,k,a[i]);
b[w]=a[i];
}
}
cout<<k<<endl;
}
}