最长上升子序列(LIS)模板
最长递增(上升)子序列问题:在一列数中寻找一些数,这些数满足:任意两个数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)模板的更多相关文章
- 求最长上升子序列(Lis模板)
实现过程 定义已知序列数组为dp[]:dp[1…8]=389,207,155,300,299,170,158,65 我们定义一个序列B,然后令 i = 1 to 8 逐个考察这个序列.此外,我们用一个 ...
- 【部分转载】:【lower_bound、upperbound讲解、二分查找、最长上升子序列(LIS)、最长下降子序列模版】
二分 lower_bound lower_bound()在一个区间内进行二分查找,返回第一个大于等于目标值的位置(地址) upper_bound upper_bound()与lower_bound() ...
- 2.16 最长递增子序列 LIS
[本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...
- 最长上升子序列LIS(51nod1134)
1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递 ...
- 动态规划(DP),最长递增子序列(LIS)
题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...
- 题解 最长上升子序列 LIS
最长上升子序列 LIS Description 给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的 ...
- 最长回文子序列LCS,最长递增子序列LIS及相互联系
最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...
- 一个数组求其最长递增子序列(LIS)
一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...
- 1. 线性DP 300. 最长上升子序列 (LIS)
最经典单串: 300. 最长上升子序列 (LIS) https://leetcode-cn.com/problems/longest-increasing-subsequence/submission ...
随机推荐
- javascript 之注意url特殊字符限制
引子 浏览器URl地址,上网一定会用到,但是浏览器地址有中文或者浏览器url参数操作的时候,经常会用到encodeURIComponent()和decodeURIComponent()以及encode ...
- 硅谷新闻8--TabLayout替换ViewPagerIndicator
1.关联库 compile 'com.android.support:design:23.3.0' 2.布局写上TabLayout <android.support.design.widget. ...
- VM虚拟机忘记密码
关掉虚拟机. VM->Settings,选中Hard Disk,在右边出现了Utilities的一个下拉栏,OK,点击它选择Map,这时弹出一个"Map Virtual Disk&qu ...
- Sass学习之路(3)——Sass编译
Sass的编译也是在我们使用Sass的时候必须要经过的一个步骤,因为".sass"和".scss"文件并不能直接使用<link>标签引用,最终其实还 ...
- .NET破解之太乐地图下载器【非暴破】
不知不觉,接触破解逆向已经三个月了,从当初的门外汉到现在的小白,这个过程只有经历过才知道其中的苦与乐: 有无知.困惑.痛苦.惊喜.彻悟.欣慰…… 有无助的软件脱壳,茫然的代码分析,有无趣的反复测试, ...
- Windows Azure 上传 VM
One of the great features of Windows Azure is VHD mobility. Simply put it means you can upload and d ...
- 新著作计划:《水利水电工程施工导流 水力计算与.NET编程》
目 录 第一篇 基础理论篇 第1章 施工导截流设计概述 第2章 基本水力计算 2.1 临界水深计算 2.2 正常水深计算 2.3 堰流水力计算 2.4 明渠流水力计算 2.5 管流水力计算 第3章 ...
- Sharepoint学习笔记—习题系列--70-573习题解析 -(Q127-Q130)
Question 127You create a custom list named Products.You need to perform a Representational State Tra ...
- 基础学习day08---多态、简单工厂、Object类equals和toString
一.多态 1.1.多态概念 定义:某一类事物的多种存在形态. 例:动物中猫,狗. 猫这个对象对应的类型是猫类型:猫 x = new 猫(); 同时猫也是动物中的一种,也可以 ...
- iOS开发笔记13:顶部标签式导航栏及下拉分类菜单
当内容及分类较多时,往往采用顶部标签式导航栏,例如网易新闻客户端的顶部分类导航,最近刚好有这样的应用场景,参考网络上一些demo,实现了这种导航效果,记录一些要点. 效果图(由于视频转GIF掉帧,滑动 ...