LIS 堆优化
Posted sshwy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LIS 堆优化相关的知识,希望对你有一定的参考价值。
LIS 问题描述
给出一个数列,找出其中最长的单调递减(或递增)子序列。
例如,A10,22,9,33,21,50,41,60,80 LIS 的长度是 6,LIS 为 10,22,33,50,60,80。
分析
定义 f[i] 表示以 A[i] 结尾的 LIS 的长度,动态转移方程如下:
f[i]=max(f[i],f[j]+1) (j<i and A[j]<A[i])
更人性化的解读参考 GavinZheng- 最长上升子序列
时间复杂度 O(n^2)
方案优化
用 l[i] 表示已遍历的长度为 i 的 LIS的最小的结尾数字
则可证明,l[] 数组的元素保持单调上升,于是用二分优化,
#include<iostream>
#include<cstdio>
using namespace std;
int n,a,l[10001],cnt;
int low_bound(int * arr,int l,int r,int v)while(l<r)int mid=(l+r+1)>>1;
if(arr[mid]>=v)r=mid-1;
else l=mid;
return l;
int main()cin>>n;
for(int i=1;i<=n;i++)cin>>a;
int j=low_bound(l,0,cnt,a);
if(++j>cnt)l[++cnt]=a;
if(l[j]>a)l[j]=a;
cout<<cnt;
return 0;
时间复杂度 O(nlogn)
以上是关于LIS 堆优化的主要内容,如果未能解决你的问题,请参考以下文章
[Mdp] lc673. 最长递增子序列的个数(LIS+算法优化+算法拓展)