最长上升子序列O(NlogN)算法

题目

给出一个长度为N的序列,请求出其最长上升子序列的长度。

题解

分析

首先很容易想到O(N2)的算法

f[i]表示1~i最长上升子序列长度则

f[i]=max{f[j]}+1,(1≤j<i)∧(a[j]<a[i])

显然我们需要的只是满足(1≤j<i)∧(a[j]<a[i])这一条件的最大f[j],那么我们为何不将他记录下来呢

用g[i]表示f[j]=i 时的 a[j]min len表示当前最大上升自序列长度

易证:

  • g[k]在程序运行过程中不会变得更大 (1≤k≤len)
  • g[k?1]<g[k] (1≤k≤len)

    于是我们可以二分查找比a[i]小的最后一个g[k],则

    len=max{len,k+1}

    g[k+1]=a[i]

    这样就可以O(Nlog2N)地解决此题了

代码

#include<cstdio>
#include<algorithm>
using namespace std;

int n,a[100050];
int c[100050];
int len=0;

int find (int x)
{
    int l=1,r=len,mid;
    while (l<=r) {
          mid=(l+r)>>1;
          if (x>c[mid]) l=mid+1;
          else r=mid-1;
    }
    return l;
}
int main()
{
    freopen("lis.in","r",stdin);
    freopen("lis.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++) {
        int k=find(a[i]);
        c[k]=a[i];
        len=max(len,k);
        }
    printf("%d",len);
    return 0;
}


膜拜所有膜拜我的人

版权声明:蒯代码有风险,爆0概不负责;随意转载,注明地址

时间: 2024-10-09 03:07:46

最长上升子序列O(NlogN)算法的相关文章

最长递增子序列 O(NlogN)算法

https://www.felix021.com/blog/read.php?entryid=1587&page=3&part=1 感谢作者! 标题:最长递增子序列 O(NlogN)算法 出处:Blog of Felix021 时间:Wed, 13 May 2009 04:15:10 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1587  内容: 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久

(转载)最长递增子序列 O(NlogN)算法

原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素.注意d中元素是单调递增的,下面要用到这个性质.首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],

最长上升子序列O(nlogn)算法详解

最长上升子序列 时间限制: 10 Sec   内存限制:128 MB 题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子序列长度是多少? 输入 第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N) 输出 1行,表示最长上升子序列的长度是多少. 样例输入 3 0 0 2 样例输出 2 提示 100%的数据 n&l

51nod 1134 最长递增子序列 (O(nlogn)算法)

1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输

最长上升子序列 O(nlogn)解法 (转)

转自 http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更

最长递减子序列(nlogn)(个人模版)

最长递减子序列(nlogn): 1 int find(int n,int key) 2 { 3 int left=0; 4 int right=n; 5 while(left<=right) 6 { 7 int mid=(left+right)/2; 8 if(res[mid]>key) 9 { 10 left=mid+1; 11 } 12 else 13 { 14 right=mid-1; 15 } 16 } 17 return left; 18 } 19 20 int Lis(int a[

最长上升子序列问题 nlogn 实现算法的简述

首先举个例子说明最长上升子序列(longest increasing subsequence 缩写 LIS): 1,4,6,2,3,7,5 中1,2,3,5 和1,4,6,7都是最长上升子序列,长度均为4,且相邻元素不能相等. LIS是动态规划中的经典问题,O(n2)的做法是设d(i)为以i为结尾的最长上升子序列的长度,状态转移方程为:d[i]=max{0,d[j]|j<i,A[j]<A[i]}+1. 下面我们仔细思考以下情况: i<j时,d[i]=d[j],显然这种情况只能是A[i]&

P3402 最长公共子序列(nlogn)

P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: 给定两个长度分别为n和m的序列,序列中的每个元素都是正整数.保证每个序列中的各个元素互不相同.求这两个序列的最长公共子序列的长度. DJL最讨厌重复劳动,所以不想做那些做过的题.于是他找你来帮他做作业. 输入输出格式 输入格式: 第一行两个整数n和m,表示两个数列的

Bridging signals(求最长上升自序列nlogn算法)

Bridging signals Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2582    Accepted Submission(s): 1665 Problem Description 'Oh no, they've done it again', cries the chief designer at the Waferlan