码迷,mamicode.com
首页 > 其他好文 > 详细

最长上升子序列(LIS)

时间:2019-11-26 22:58:08      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:stream   else   数字   lis   因此   ret   ios   二分   clu   

O(nlogn)

q[i]表示所有不同长度的最长上升子序列结尾的最小值。因为如果a[i]<a[j]<a[j+1],那么a[j+1]肯定大于a[i],因此我们只存最小值。

我们通过第i-1个数字来划分状态,由于子序列是递增的,所以可以通过二分查找出来小于a[i]的最大的那个数字。找到之后,将a[i]放在它之后,长度加一。并且由于子序列是递增的,那么若找到的数字为a[k],那么a[k+1]一定大于等于a[i]。所以可以用a[i]来更新a[k+1].

 

#include<iostream>
#include<cmath>
using namespace std;

const int maxn=1e5+10;
int a[maxn];
int q[maxn];//所有不同长度的最长上升子序列结尾的最小值
int main()
{

    int n;
    cin >> n;
    for(int i=0;i<n;i++)
    {
        cin >> a[i];
    }
    int len=0;//最长上升子序列的长度
    //q[0]=-2e9;
    for(int i=0;i<n;i++)
    {
        int l=0,r=len;
        while(l<r)
        {
            int mid=l + r + 1>> 1;
            if(q[mid]<a[i]) l=mid;
            else
            r=mid-1;
        }
        len=max(len,r+1);
        q[r+1]=a[i];
    }
    cout << len << endl;
    return 0;    
}

 

最长上升子序列(LIS)

标签:stream   else   数字   lis   因此   ret   ios   二分   clu   

原文地址:https://www.cnblogs.com/wjc2021/p/11938811.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!