最长上升子序列nlog(n)

最长上升子序列——O (nlogn)算法原因解析!为什么这样可以求出来!(附带动态规划dp + 二分查找讲解) 什么是最长上升子序列 网上流传着一个O (nlogn)算法,大体是这样的。 模拟一个栈,如果当前的数比栈顶元素大,就要入栈,如果比栈顶元素小,就二分查找到刚好比当前数大的数,然后进行替换。本例的流程是这样的。 2 入栈 当前栈:2 5 比2大 入栈 当前栈:2 5 3 比5小 替换5 当前栈:2 3 4 比3大 入栈 当前栈: 2 3 4 1比2小 替换2 当 阅读详情

nlog(n)的方法从很久之前就看了,愣是没看懂,因为这个条件

现在,我们仔细考虑计算F[t]时的情况。假设有两个元素A[x]和A[y],满足 (F[]保存LIS长度)
(1)x < y < t 
(2)A[x] < A[y] < A[t] 
(3)F[x] = F[y] 

没看懂,当A[x]<A[y]时,怎么会F[x]=F[y]呢?

其实这只是传递一个思想而已,当两者的LIS都一样时取最小值效果更好。只要明白这一点就行了。


再根据那个思想,我们会得到一个启示:根据F[]的值进行分类。对于F[]的每一个取值k,我们只需要保留满足F[t] = k的所有A[t]中的最小值。设D[k]记录这个值,即D[k] = min{A[t]} (F[t] = k)。 

注意到D[]的两个特点: (这个特点很重要)
(1) D[k]的值是在整个计算过程中是单调不下降的。 
(2) D[]的值是有序的,即D[1] < D[2] < D[3] < ... < D[n]。 

利 用D[],我们可以得到另外一种计算最长上升子序列长度的方法。设当前已经求出的最长上升子序列长度为len。先判断A[t]与D[len]。若A [t] > D[len],则将A[t]接在D[len]后将得到一个更长的上升子序列,len = len + 1, D[len] = A [t];否则,在D[1]..D[len]中,找到最大的j,满足D[j] < A[t]。令k = j + 1,则有A [t] <= D[k],将A[t]接在D[j]后将得到一个更长的上升子序列,更新D[k] = A[t]。最后,len即为所要求的最长上 升子序列的长度。 

在 上述算法中,若使用朴素的顺序查找在D[1]..D[len]查找,由于共有O(n)个元素需要计算,每次计算时的复杂度是O(n),则整个算法的 时间复杂度为O(n^2),与原来的算法相比没有任何进步。但是由于D[]的特点(2),我们在D[]中查找时,可以使用二分查找高效地完成,则整个算法 的时间复杂度下降为O(nlogn),有了非常显著的提高。需要注意的是,D[]在算法结束后记录的并不是一个符合题意的最长上升子序列!

例如:

  0 1 2 3 4 5 6
a[] 1 7 3 5 9 4 8
c[] -1 1  3(7)(4) 5     9(8)  

#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdio>

using namespace std;
#define N 200001
int n,a[N],dp[N];
int find(int len,int n)   //二分,返回值为x,则c[x]>n>c[i-1],返回比n大的最小值
{
    int mid,l=1,r=len;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(dp[mid]>n)
        r=mid-1;
        else if(dp[mid]<n)
        l=mid+1;
        else
        return mid;
    }
    return l;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        cin>>a[i];
        for(int i=0;i<=n+1;i++)
        dp[i]=N;
        dp[1]=a[0];
        int max=1;
        for(int i=1;i<n;i++)
        {
            int d=find(max,a[i]);  //不知为什么max改为i+1就不能过了,但是在hdu上能过
            dp[d]=a[i];
            if(d>max)
            max=d;
        }
        cout<<max<<endl;
    }
    return 0;
}

有个更剪短优化的代码,就是利用STL中的lower_bound

函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置

函数upper_bound()返回的在前闭后开区间查找的关键字的上界,如一个数组number序列1,2,2,4.upper_bound(2)后,返回的位置是3(下标)也就是4所在的位置,同样,如果插入元素大于数组中全部元素,返回的是last。(注意:此时数组下标越界!!)

返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=100100;
int num[MAX],top=0;
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		scanf("%d",&num[0]);
		top=1;
		for(int i=1;i!=n;i++)
		{
			scanf("%d",&num[i]);
			int * p=lower_bound(num,num+top,num[i]);  //不是很懂
			if(p-num==top) ++top;
			*p=num[i];
		}
		printf("%d\n",top);
	}
	
}        






        
最长上升子序列 (LIS) 详解+例题模板 (全) 欢迎访问https://blog.youkuaiyun.com/lxt_Lucia~~ 宇宙第一小仙女\(^o^)/~~萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗~~ ------------------------------------我只是一条可爱哒分界线-------------------------------------- 1.摘要: 关... 阅读详情

相关推荐

最长公共子序列nlogn算法

求两个序列的最大公共子序列(LCS),普遍的动态规划算法时间复杂度为O(n^2),在两个序列的长度很长的时候运行时间过长。可以转化为最长上升子序列(LIS)来求,时间复杂度可以优化到nlogn。1.首先说一下转化为LIS的方法:  找到s1序列中每个元素在s2序列中的位置,并用这些在s2中的位置替换s1中对应的元素,注意s1中的元素在s2中当有多个位置(a1,a2,a3……)时,要降序排列(a1>a

zhijianshafeiyang的专栏 5072

LIS 最长上升子序列N^2以及nlogn算法

<br />这题目是经典的DP题目,也可叫作LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列。很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) 。<br /><br />A.<br />O(n^2)算法分析如下: <br /><br />(a[1]...a[n] 存的都是输入的数) <br />1、对于a[n]来说,由于它是最后一个数,所以当从a[n]开始查找时,只存在长度为1的不下降子序列; <br />2、若从a[n-1]

1896

LeetCode:300 最长上升子序列 O(nlog(n))解法 动态规划/二分搜索

题目 给定一个无序的整数数组,找到其中最长上升子序列的长度。 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。 说明: 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。 你算法的时间复杂度应该为 O(n2) 。 进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗? 来源:力扣(L...

AKGWSB 's blog 532

关于最长上升子序列的nlogn时间复杂度的DP算法详解(易懂)

那是肯定有用啊 ,因为我们通过不断的更新以后,我们会把DP数组元素变得尽可能地小,导致我们可能会把最右边的数字更新得更小,使得增加长度更容易,这很棒不是吗?当长度为2时,我们可以取的序列有 {2,3} {2,4} {2,5},{2,8}…很明显,如果它比6大,说明,我们可以得到序列 2 3 4 5 6 10,所以我们就可以将答案和DP数组的长度更新为6,同时DP[6]=10。我们当然不能忽略这个数字,当它等于2的时候,我们可以知道,我们可以得到上升序列为{1 2},所以DP[2]应该等于2才对。

qq_42893945的博客 1835

微信小程序如何集成EasyRTC实现零插件音视频通话?5步搞定完整接入流程

本文详细介绍了如何在微信小程序中集成EasyRTC SDK,实现零插件的实时音视频通话功能。通过5个关键步骤,包括环境配置、SDK初始化、核心功能实现、性能优化和问题排查,帮助开发者快速完成WebRTC技术在小程序中的落地应用,解决微信小程序原生不支持实时音视频通信的技术难题。

weixin_28340315的博客 143

【实战解析】RTL8306MB交换芯片驱动开发中的RMII接口调试陷阱

本文通过一个RTL8306MB交换芯片驱动开发的实战案例,深入剖析了RMII接口调试中的经典陷阱。文章详细描述了因TX_EN与CRS_DV信号线交叉连接错误导致的“静默”故障,并分享了使用逻辑分析仪和示波器进行硬件排查的完整流程与核心技巧,为嵌入式网络驱动开发提供了宝贵的避坑指南。

weixin_29267307的博客 421

最长上升子序列(nlog(n))

我们可以先将输入的数据全部离线化处理,尔后用nlog(n)方法,处理上升子序列,对x进行特判就可以。2 7 分析这两个样例我们就可以看出后者的答案一定大于等于前者,根据这个答案的不降性质。2 3(下标为2之前的数字里面找最大上升子序列的长度,而且,里面最大的值不超过x)言简意赅,给定下标x,往前找最大上升子序列,且最大值不能超过x,找到最大的长度。首先我们对题目进行分析,不难看出,答案有一定的二分性质,不降。还是周赛题目,遇到了一个思维量和模板题目结合在一起的。离线处理,最大上升优化,不降二分答案。

dulcet_23的博客 315

RK3588嵌入式AI部署实战:从环境搭建到模型推理全链路

嵌入式AI部署涉及交叉编译、NPU驱动、模型量化与运行时环境等多个技术环节,其核心挑战在于软硬件版本矩阵的严格匹配。在边缘计算场景中,RK3588凭借6TOPS NPU算力成为热门平台,但环境搭建与模型转换的复杂性常导致部署效率低下。通过容器化工具链管理、量化参数对齐及多线程推理优化,可显著提升部署稳定性与推理性能。典型应用包括智能安防、工业质检与视频结构化分析。本文围绕RK3588的AI部署与环境搭建,系统梳理从系统烧录到板端推理的完整实践路径。

weixin_42520573的博客 282

最长上升子序列 nlog(n)

最近在做单调队列,发现了最长上升子序列O(nlogn)的求法也有利用单调队列的思想。     最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i    设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1    这样简单的复杂度为O(n^2),其实还有更好的方法。  

远古小山的专栏 551

芯片设计中的“隐形杀手”:手把手教你理解并优化互连寄生参数(以SPEF/DSPF为例)

本文深入探讨了芯片设计中互连寄生参数的影响及优化策略,特别关注SPEF/DSPF文件解析与静态时序分析。通过实际案例展示了耦合电容对时序收敛的关键影响,并提供从定位到优化的完整解决方案,助力工程师应对先进工艺下的设计挑战。

weixin_30687051的博客 597

Excel数字变成了小数点+E+17?这些方法帮你解决!

本文介绍了三种解决Excel中数字变成小数点+E+17问题的方法:通过下拉箭头或右键菜单设置单元格格式为文本、使用TEXT函数将科学计数法转换为文本。这些方法各有优缺点,适用于不同的场景和需求。在实际应用中,我们可以根据具体情况选择合适的方法来解决问题。通过以上方法,我们可以轻松地从繁琐的小数点+E+17问题中解脱出来,更便捷地处理Excel中的数字。希望本文能够帮助到您,让您在使用Excel时更加得心应手!

nntxthml的博客 1245

【最长上升子序列nlog(n)】

#include #include #include #include #include using namespace std; typedef long long LL; const int N=1005; int a[N],d[N],n; int LIS() { d[1]=a[1]; int len=1,p; for(int i=2;i<=n;i++) {

tystrwor的博客 433

电商行业分析爬虫:抓取行业数据,进行行业分析

电商行业数据分析对于市场研究、竞争分析和商业决策至关重要。通过爬取电商平台的数据,我们可以深入了解市场动态、消费者行为和商品销售情况。本文将介绍如何构建一个电商行业分析爬虫,抓取商品信息、销售数据和用户评价等,并进行数据分析。

u014481728的博客 1628

最长上升子序列O(nlog(n))

思路:从头到尾扫一遍序列,用一个数组ans保存当前最长的上升序列,如果扫到的元素大于当前上升序列的最后一个,那么就把该元素加在ans序列末尾,否则,将该元素替换ans序列中第一个比该元素大的元素,如果没有则替换最后一个。替换过程使用二分处理。 #include &lt;string.h&gt; #include &lt;stdio.h&gt; int num[1005]; int ans[10...

bpdwn2017的博客 434

效果炸裂_安装midscene_copw基于midscene操作电脑_基于视觉的软件测试执行_MIDSCENE的安装和使用---AI大模型应用探索0012

摘要:本文介绍了如何通过安装MidSceneJS来增强Copaw的屏幕操作能力。首先需要安装Node.js和npm,并配置淘宝镜像源加速安装。然后全局安装MidScene CLI工具(npm install @midscene/cli -g)。接着配置视觉大模型服务,通过设置环境变量指定模型API密钥、名称、基础URL和家族类型(如qwen3.5-27b),配置文件需存放在C:\Users\Administrator.copaw目录。安装成功后,MidScene已能成功识别并操作屏幕,使用效果良好。文中还提

添柴程序猿的专栏 638

【ComfyUI】Flux + ControlNet 边缘搭配深度、瓷砖、姿态引导图生图

本文介绍了一个基于 Wan 2.1 的 ComfyUI 文生视频工作流,通过 UNet、CLIP 和 VAE 三个核心模型,将文本提示转化为动态视频。工作流包含模型加载、提示词解析、潜空间采样等7个环节,支持分辨率、帧数等参数设置,最终输出高质量视频文件。该方案适用于创意设计、教育培训和多媒体制作等场景,能快速生成符合语义的动态内容。文章还提供了相关开发资源和学习链接,适合AI视频生成领域的研究者和实践者参考。

Mr数据杨 1632

poj 3903 最长上升子序列,nlog(n)的算法

OJ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define PF(x) (scanf("%d",&x)) #define PT(x

JogRunner的专栏 1403

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

POJ 1631 : Bridging signals - 最长上升子序列 O(nlog n)

题目大意:给定两个相同序列,单个序列中数字不会重复,x出现在y位置,即代表x与y可以连线。最后要从这个序列中尽量多地选择连线并保证连线不交叉。思路:一个序列已经固定,那只要保证另一列被选择的数是递增的就不会相交了,画几个模拟就明白,模拟过程参考http://www.cnblogs.com/zhsl/archive/2013/05/21/3089983.html,红色航线是合法的,那么他们满足什么规

Booky的专栏 756

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

nlog(n)解动态规划--最长上升子序列(Longest increasing subsequence)

    最长上升子序列LIS问题属于动态规划的初级问题,用纯动态规划的方法来求解的时间复杂度是O(n^2)。但是如果加上二叉搜索的方法,那么时间复杂度可以降到nlog(n)。   具体分析参考:http://blog.chinaunix.net/uid-26548237-id-3757779.html   代码: #include &lt;iostream&gt; using na...

weixin_34034670的博客 156

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

最长上升子序列(nlog n)

呵呵 program hehe;var n,i,j,k,l:longint; d,f,a:array[0..5000] of longint; function find(l,r:longint):longint; var mid:longint; begin if l=r then exit(l); mid:=(l+r)>>1; if d[mid]>...

weixin_34378922的博客 157

hdu 5489(LIS最长上升子序列)

题意:一个含有n个元素的数组,删去k个连续数后,最长上升子序列        /*思路参考GoZy 思路: 4 2 3 [5 7 8] 9 11 ,括号表示要删掉的数, 所以  最长上升子序列  =   ] 右边数A的lis + [左边最大值小于A的lis  即相当于枚举删除的所有情况,并求它们的LIS,取最大值 如本例 : 最长 = 2[ 9 11]  + 2[2 3],  然后将框从左

阳光下的泡沫 1030

hdu 6197 最长上升子序列 o(nlog(n))版

array array array Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 610    Accepted Submission(s): 352 Problem Description One day,

eletroram的博客 289

POJ 1631 Bridging signals [最长上升子序列O(nlog(n))]

描述:要为电路板搭线,要求不能交叉,如图,左边的线柱按升序排好,只需在右边线柱中找最长上升子序列。需要用二分优化。 思路:在O(n*n)算法的基础上,加入一个辅助数组best[],下标表示子序列长度,对应值表示所有该长度的序列中的最小头儿, 维护这个数组,更新数组。对于新增的数x,找到位置k,使best[k-1]<x ,且best[k]>x,则best[k] = x。设b...

weixin_34302561的博客 87
上一篇: 校OJ 17089 最大m子段和
下一篇: 11078 不能移动的石子合并(dp)
BIGKAKA
博客等级 码龄11年 32粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值