首先举个例子说明最长上升子序列(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]>=A[j];这时我们计算 d[t](t>j且A[t]>A[i]),那么应优先选取以A[j]结尾的子序列作为A[t]的前缀序列,因为如果存在

i<j<z<t,满足A[j]<A[z]<A[i]<A[t],子序列的长度会因z的存在而增加。

  由此我们使用数组D[k]保存满足d[t]=k的最小A[t],即D[k]=min{A[t]|d[t]=k};

  可以证明D[k]是严格单调递增的,即D[1]<D[2]<D[3]<……<D[len],

证明如下:

  D[k]=min{A[t1]|d[t1]=k};

  D[k+1]=min{A[t2]|d[t2]=k+1};

  采用反证法,

  令A[t1]=D[k],A[t2]=D[k+1]

  假设A[t2]<A[t1];

  设以A[t2]结尾对应的子序列为S[1]~S[k],A[t2],  满足S[k]<A[t2].

  显然S[1]~S[k]是一个以S[k]为结尾的最长上升子序列,长度为k,

  则有A[t1]=D[k]<=S[k]<A[t2],与假设矛盾,故D为严格单调递增序列。

于是利用D我们可以得到另外一种计算最长上升子序列的方法,并且可以边读边计算D,算法如下:

  1)设当前最大子序列长度为len,读入A[i];

  2)如果A[i]>D[len],则len++,D[len]=A[i];

  3)如果A[i]<=D[len],则从1~len中二分查找第一个k,使D[k]>=A[i],更新D[k]=A[i].

代码如下:

   int n;//原序列长度
cin>>n;
memset(A, ,sizeof A);
memset(D, , sizeof D);
int len=;//当前最长子序列长度
for(int i=;i<n;i++){
cin>>A[i];
if(A[i]>D[len]){
len++;
D[len]=A[i];
}
else {
int k=lower_bound(D, D+len, A[i])-D;//二分搜索D[k]>=A[i],更新D[k]
D[k]=A[i];
}
}
cout<<len<<endl;
return ;

最长上升子序列问题 nlogn 实现算法的简述的更多相关文章

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

    最长递减子序列(nlogn): int find(int n,int key) { ; int right=n; while(left<=right) { ; if(res[mid]>ke ...

  2. LCS(最长公共子序列)动规算法正确性证明

    今天在看代码源文件求diff的原理的时候看到了LCS算法.这个算法应该不陌生,动规的经典算法.具体算法做啥了我就不说了,不知道的可以直接看<算法导论>动态规划那一章.既然看到了就想回忆下, ...

  3. 洛谷1439:最长公共子序列(nlogn做法)

    洛谷1439:最长公共子序列(nlogn做法) 题目描述: 给定两个序列求最长公共子序列. 这两个序列一定是\(1\)~\(n\)的全排列. 数据范围: \(1\leq n\leq 10^5\) 思路 ...

  4. 从最长公共子序列问题理解动态规划算法(DP)

    一.动态规划(Dynamic Programming) 动态规划方法通常用于求解最优化问题.我们希望找到一个解使其取得最优值,而不是所有最优解,可能有多个解都达到最优值. 二.什么问题适合DP解法 如 ...

  5. 浅谈最长上升子序列(O(n*logn)算法)

    今天GM讲了最长上升子序列的logn*n算法,但没讲思路... 我看了篇博客,发现-- 说的有道理!!! 首先,举例子: a[7]={1,2,4,3,6,7,5}(假设以1开头) 很明显,LIS=5: ...

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

    原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则 ...

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

    转自:点击打开链接 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS. 排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了. 假设存在一个 ...

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

    最长上升子序列 时间限制: 10 Sec   内存限制:128 MB 题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子 ...

  9. P3402 最长公共子序列(nlogn)

    P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子 ...

随机推荐

  1. 【转载】【python】python练手项目

    入门篇 1.Python - Python 图片转字符画 50 行 Python 代码完成图片转字符画小工具. &lt;img src="https://pic3.zhimg.com ...

  2. poj2125 最小点权覆盖集

    题意:有一张图,对于每个点,有出边和入边,现在目的是删除改图的所有边,对于每个点,删除出边的花费Wi-,删除入边的花费Wi+,现在的目的求删去所有边后的花费最小. 建图方法:对于每个点i,拆点为i,i ...

  3. oracle如何加固你的数据库

    要注意以下方面 1. 修改sys, system的口令. 2. Lock,修改,删除默认用户: dbsnmp,ctxsys等. 3. 把REMOTE_OS_AUTHENT改成False,防止远程机器直 ...

  4. Eclipse中提示 找不到类 javax.servlet.http.HttpServletResponse

    问题如题, 解决方案如下: 复制tomcat的安装路径下\lib\servlet-api.jar 到WEB-INF/lib下即可.

  5. poj3469 最小割

    最大流之后S集合与T集合不在相连,即s不能到达T中的点. 对于同一个模块,Ai,Bi,Ai与源点相连,Bi与汇点相连.不同CPU间消耗的模块,相连. 由于最后模块只能在一个CPU中运行,所以要么与源点 ...

  6. Java SDUT-2562_相似三角形

    相似三角形 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给出两个三角形的三条边,判断是否相似. Input 多组数据 ...

  7. Java练习 SDUT-1588_圆的面积

    圆的面积 Time Limit: 1000 ms Memory Limit: 32768 KiB Problem Description Give you the radius of a circle ...

  8. HZOJ Drink

    神仙题,打了个whs式暴力卡常卡A了(我没脸),正解还是要打的,然而作者的题解看不懂…… Drink: 看惯了罗马音的小朋友们都会知道r发l的音,题目名:D Link. 每次修改都会改变O( N ^  ...

  9. Android 整合实现简单易用、功能强大的RecyclerView

    之前总是会有人在一些开发群里问,有木有比较好使且功能强大些的RecyclerVew,比如支持下来刷新,加载更多等,还有人在问,如何为RecyclerView添加分割线,尤其是如何为网格布局添加分割线? ...

  10. tf.cast用法

    tf.cast:用于改变某个张量的数据类型 例如: import tensorflow as tf;import numpy as np; A = tf.convert_to_tensor(np.ar ...