最大上升子序列--LIS
最大上升子序列
思路:
建立一个low数组,用于存放上升的子序列,并记录长度,如果一个数大于low的最后一个数,则将他添加到low数组最后面,如果不大于,则将那个数利用二分放在low合适的位置,以便下次比较。
时间复杂度O(nlogn)
Code:
#include<iostream> #include<algorithm> #include<cmath> using namespace std; const int N=1e6+5; int n,len;//n为a数组的长度,len为low数组的长度 int a[N],low[N]; int find(int x) { int l=1,r=len; while(l<=r)//二分查找 { int mid=(l+r)>>1; if(x>=low[mid]) l=mid+1; else r=mid-1; } return l; } void lis() { low[1]=a[1];//默认第一个数是上升的 len=1;//此时low的长度为1 for(int i=2;i<=n;i++) { if(a[i]>low[len])//判断当前数是不是大于low数组中最后的数 { low[++len]=a[i];//如果大于,则将他添加到low数组中 长度自增1 } else { low[find(a[i])]=a[i];//如果小于 则更新low数组 } } } int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; low[i]=989898;//给low数组赋最大值 } lis(); cout<<len<<endl; return 0; }