LIS问题
求序列具有单调性的最长子序列,我们可以用到动态规划的方法来解决问题
我们用 来表示下标i位置可以找到的具有单调性的最长子序列的长度,
的状态转移方程如下:
使用两层for循环就可以解决此问题,时间复杂度为,可以处理n<7000左右的数据
#include<bits/stdc++.h>
using namespace std;
int f[100001];
int h[100001];
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>h[i],f[i]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(h[i]>h[j])
f[i]=max(f[i],f[j]+1);//求单调递增序列
cout<<f[n];
return 0;
}
如果n的数据规模较大时,这种方法就不是很适宜了,那么我们可以使用二分搜索+记忆化搜索来优化LIS,时间复杂度为
#include<bits/stdc++.h>
using namespace std;
int h[100001];
int f[100001];
int n;
int len;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>h[i];
f[0]=-1e9;//给定边界
for(int i=1;i<=n;i++){
if(f[len]<h[i]){
f[len+1]=h[i];
len++;
} else{
int loc=lower_bound(f,f+len,h[i])-f;
if(loc)
f[loc]=h[i];
}
}
cout<<len;
}