LIS问题$n log_2 n$做法(二分优化)

#include<bits/stdc++.h>
using namespace std;
const int inf=1e9+5;
const int maxn=1e6+5;
int n,a[maxn];
int back[maxn],cnt;
//log_2 n 重点数组,记录长度为cnt的LIS最小or大的结尾数字 
//显然,back为 单调递增or递减 所以可以使用二分查找
int find(int l,int r,int d){
	while(l<r){
		int mid=(l+r)>>1;
		if(back[mid]>d)r=mid;//符号视情况而定
		else l=mid+1;
	}
	return l;//返回下标
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		back[i]=inf;
	}
	back[0]=0;back[1]=a[1];cnt=1;
	for(int i=2;i<=n;i++){
		if(a[i]>back[cnt])
			back[++cnt]=a[i];
        //如果恰为大于,直接加入back数组,不破坏单调性
		else {
			int q=find(1,cnt,a[i]);
			back[q]=min(back[q],a[i]);
            //如果不可,则更新末尾最小值
		}
	}
	cout<<cnt;
	return 0;
}

终于弄懂啦!!

posted @ 2019-04-23 23:04  永远_少年  阅读(296)  评论(0编辑  收藏  举报