AcWing 896. 最长上升子序列 II(二分优化LIS)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 896. 最长上升子序列 II(二分优化LIS)相关的知识,希望对你有一定的参考价值。

题目连接

https://www.acwing.com/problem/content/description/898/

思路

我们用一个 f [ i ] f[i] f[i]表示以长度为i结尾的子序列的最小值的大小,那么不难发现我们这个f数组是一个单调递增的序列,那么我们就能对我们往前匹配的过程做一个二分优化,也就是找到长度尽量大的且比当前 a [ i ] a[i] a[i]值小的一个位置,如果我们发现当前的这个 a [ i ] a[i] a[i]是比之前所有的元素都要大的,那么我们就应该让我们的最长序列的长度增加,并将 a [ i ] a[i] a[i]放在末尾,表示长度为 l e n len len子序列的末尾最小值,否则的话我们就去更新之前长度的末尾最小值,因为如果一个人比你小还在你后面,那你也没存在的必要了

代码

代码版本一

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
int a[N],n,f[N];

int LIS()
    f[1] = a[1];
    int len = 1;
    for(int i = 2;i <= n; ++i)
        if(a[i] > f[len]) 
            f[++len] = a[i];
        else
            f[lower_bound(f + 1,f+len+1,a[i]) - f] = a[i];
    return len;


int main()

    
    cin>>n;
    for(int i = 1;i <= n; ++i) cin>>a[i];
    f[1] = a[1];
    
    cout<<LIS()<<endl;
    return 0;

模板代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
int n;

template<typename T>
int LIS(vector<T> a) 
    vector<T> dp;
    for(auto x : a) 
        auto it = lower_bound(dp.begin(), dp.end(), x);
        if(it == dp.end()) dp.push_back(x);
        else *it = x;
    
    return dp.size();


int main()

    
    cin>>n;
    vector<int> a(n);
    for(int i = 0;i < n; ++i) cin>>a[i];
    cout<<LIS(a)<<endl;
    
    
    return 0;

以上是关于AcWing 896. 最长上升子序列 II(二分优化LIS)的主要内容,如果未能解决你的问题,请参考以下文章

AcWing 895 最长上升子序列 - (线性DP) or (贪心+二分优化)

最长上升子序列模型

acwing 272. 最长公共上升子序列

AcWing 1490. 最长上升子串 模拟优化

AcWing 272. 最长公共上升子序列

数字三角形模型和最长上升子序列模型 AcWing题目