最长递增(上升)子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增(上升)子序列。

考虑两个数a[x]和a[y],x>y且a[x]<a[y],且dp[x]=dp[y],当a[t]要选择时,到底取哪一个构成最优的呢?显然选取a[x]更有潜力,因为可能存在a[x]<a[z]<a[y],这样a[t]可以获得更优的值。在这里给我们一个启示,当dp[x]一样时,尽量选择更小的a[x].

按dp[t]=k来分类,只需保留dp[t]=k的所有a[t]中的最小值,设d[k]记录这个值,d[k]=min{a[t](dp[t]=k)}。

这时注意到d的两个特点(重要):

1. d[k]在计算过程中单调不升;

2. d数组是有序的,d[1]<d[2]<..d[n]。

利用这两个性质,可以很方便的求解:

1. 设当前已求出的最长上升子序列的长度为len(初始时为1),每次读入一个新元素x:

2. 若x>d[len],则直接加入到d的末尾,且len++;(利用性质2)

否则,在d中二分查找,找到第一个比x小的数d[k],并d[k+1]=x,在这里x<=d[k+1]一定成立(性质1,2)。

#include<stdio.h>
#include<string.h>
const int N=;
int d[N];
int bs(int a[],int l,int r,int key)
{
while(l<r)
{
int mid=((l+r)&)+(l+r)>>;
if(a[mid]<key)
l=mid;
else
r=mid-;
}
if(a[l]>=key) return l-;
return l;
}
int LIS(int a[],int n)
{
int i,tmp,len=;
d[]=a[];
for(i=;i<=n;i++)
{
if(d[len]<a[i])
tmp=++len;
else
tmp=bs(d,,len,a[i])+;
d[tmp]=a[i];
}
return len;
}
int main()
{
int a[]={-,,,,,,};
int tmp=LIS(a,);
printf("%d\n",tmp);
for(int i=;i<=tmp;i++)
printf("%d ",d[i]);
printf("\n");
return ;
}

LIS

这种算法的时间复杂度是O(nlogn),但是稍微难写了一点。下面的是O(n^2),容易编写。

 int LIS(int *a,int n)
{
int i,j,ans=-;
memset(dp,,sizeof(dp));dp[]=;
for(i=;i<=n;i++)
{
for(j=;j<i;j++)
{
if(a[i]>a[j])
{
if(dp[j]+>dp[i])
dp[i]=dp[j]+;
}
}
}
for(int i=;i<=n;i++)
if(dp[i]>ans)
ans=dp[i];
return ans;
}

参考文章:http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html

最长上升子序列(LIS)模板的更多相关文章

  1. 求最长上升子序列(Lis模板)

    实现过程 定义已知序列数组为dp[]:dp[1…8]=389,207,155,300,299,170,158,65 我们定义一个序列B,然后令 i = 1 to 8 逐个考察这个序列.此外,我们用一个 ...

  2. 【部分转载】:【lower_bound、upperbound讲解、二分查找、最长上升子序列(LIS)、最长下降子序列模版】

    二分 lower_bound lower_bound()在一个区间内进行二分查找,返回第一个大于等于目标值的位置(地址) upper_bound upper_bound()与lower_bound() ...

  3. 2.16 最长递增子序列 LIS

    [本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...

  4. 最长上升子序列LIS(51nod1134)

    1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递 ...

  5. 动态规划(DP),最长递增子序列(LIS)

    题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...

  6. 题解 最长上升子序列 LIS

    最长上升子序列 LIS Description 给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的 ...

  7. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  8. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  9. 1. 线性DP 300. 最长上升子序列 (LIS)

    最经典单串: 300. 最长上升子序列 (LIS) https://leetcode-cn.com/problems/longest-increasing-subsequence/submission ...

随机推荐

  1. phpcms--使用添加php原生支持

    1,phpcms模板中有时候要添加一些php相关变量这个时候要使用原始php的东西,可以如下加入 {php $no_wq_id=$r[id] ;}其中$r[id]是通过{pc:get sql=&quo ...

  2. YUIDoc example代码高亮错误、生成API文档目录不按源文件注释顺序

    1.如果发现yuidoc命令用不了,那就重装nodejs吧 昨天不知道是清扫电脑的原因,yuidoc命令用不了(命令不存在),也没有找到好的解决方法,怒重装YUIDoc也不行.最后想了想,怒重装了no ...

  3. QT4/5中文乱码问题解决

    QT4 : QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QT5: #if defined(_MSC_ ...

  4. GitHub 基本常用知识解答

    1.Fork.Watch.Star 是什么意思? fork的意思是从别人的代码库中复制一份到你自己的代码库,与普通的复制不同,fork包含了原有库中的所有提交记录, fork后这个代码库是完全独立的, ...

  5. ADB server didn't ACK 解决方法

    在安卓开发的过程中 连接真机的时候 连接不上 提示 The connection to adb is down, and a severe error has occured.[2015-01-22 ...

  6. 操作数据库系统(OLTP)和联机分析处理系统(OLAP)的区别

    联机操作数据库系统的主要任务是执行联机事务和查询处理.这种系统称为联机事务处理(OnLine Transaction Processing,OLTP) 系统.它们涵盖了单位的大部分日常操作,如购物,库 ...

  7. Effective Java 阅读笔记——方法

    38:检查参数的有效性 每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制,在方法的开头处对参数进行检查,并且把这些限制写入文档. 注意: 对于公有方法,应该使用@throws标签在文档中说明违 ...

  8. iOS设计模式之备忘录模式

    备忘录模式 基本理解 这个模式有三个关键角色:原发器(Originator).备忘录(Memento).看管人(caretaker).三者的基本关系是:原发器创建一个包含其状态的备忘录,并传给看管人. ...

  9. JAVA基础学习day18--常用工具类

    一.System 1.1.概述 System 类包含一些有用的类字段和方法.它不能被实例化. 在 System 类提供的设施中,有标准输入.标准输出和错误输出流:对外部定义的属性和环境变量的访问:加载 ...

  10. UIButton 内部介绍

    **     设置内容距btn边框距离     **/    btn.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);        /** 将lab ...