浅谈最长上升子序列(LIS)
一、瞎扯的内容
给一个长度为n的序列,求它的最长上升子序列(LIS)
简单的dp
n=read();
for(i=;i<=n;i++) a[i]=read();
for(i=;i<=n;i++)
for(j=;j<i;j++)
if(a[j]<a[i])
dp[i]=max(dp[i],dp[j]+);
printf("%d",dp[n]);
然后发现


看来需要一个nlogn求LIS的算法
二、不瞎扯的内容
上一个算法慢在哪里呢?内层的循环
如果把它变成二分查找不就是nlogn的算法了吗
为此需要进行一下改动
dp数组改为存储长度为i的上升子序列中最小的末尾数字
这样每当外层循环到了一个新的数字
若
a[i]>dp[len]//新的数字比当前LIS的末尾数字大
则
dp[++len]=a[i]//愉快地把这个数字接到后面
如果它小于等于dp[len]?
举个例子
序列2 3 1
i=1:找到2,当前LIS={2},没毛病;
i=2:找到3,发现它比LIS的最后一个数字大,把它接到后面,当前LIS={2,3};
i=3:找到1,发现它比3小,那么在当前的LIS中找到一个最小的比1大的数,也就是2,并把2替换成1,当前LIS={1,3}
Q1:为什么可以这么做呢?
我们现在把2替换成了1,如果接下来还能把3替换,我们就可以得到一个更优的LIS
为什么更优?首先LIS是保证尽可能长的,在此基础上,末尾数字越小越优
Q2:如何在当前的LIS中找到一个最小的比a[i]大的数?
根据“长度一定时,末尾数字越小结果越优”原则,dp数组一定是递增的
这个递增就不做证明了,应该比较好想
所以就可以用二分查找了
问题解决
for(i=;i<=n;i++) dp[i]=0x7fffffff;
dp[]=a[];
int len=,l,r,mid;
for(i=;i<=n;i++)
{
if(a[i]>dp[len]) dp[++len]=a[i];
else
{
l=;r=len;
while(l<=r)
{
mid=(l+r)>>;
if(dp[mid]>a[i]) r=mid-;
else l=mid+;
}
dp[l]=min(dp[l],a[i]);
} }
三、来道题
题目简述:给出两个1~n的序列,求他们的最长公共子序列(n≤100000)
这跟LIS有什么关系呢?
还真有关系
不妨改为在第二个序列中匹配第一个序列,最多匹配多少
由于两个序列都是1~n的,可将第一个序列重新定义一下
比如 3 2 1 4 5
3----1;2----2;1----3;4----4;5----5(对应到它是第几个)
那么第二个序列 1 2 3 4 5就会变成3 2 1 4 5
这时再求最长公共子序列的答案是一样的
然而可以发现第一个序列已经变成了1~n的升序排列,那么第二个序列的子序列 也是第一个序列的子序列的充要条件 是 它是一个上升的序列
那么问题就变成了求第二个序列的LIS
用上述方法可以解决
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; inline int read()
{
int f=,x=;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
} int n;
int a[],b[],f[],g[]; int main()
{
int i;
n=read();
for(i=;i<=n;i++)
{
a[i]=read();
g[a[i]]=i;
}
for(i=;i<=n;i++)
{
b[i]=read();
b[i]=g[b[i]];
f[i]=0x7fffffff;
}
f[]=b[];
int len=,l,r,mid;
for(i=;i<=n;i++)
{
if(b[i]>f[len]) f[++len]=b[i];
else
{
l=;r=len;
while(l<=r)
{
mid=(l+r)>>;
if(f[mid]>b[i]) r=mid-;
else l=mid+;
}
f[l]=min(f[l],b[i]);
}
}
printf("%d\n",len);
return ;
}
~祝大家学习信息学顺利~
BJOI 加油!
浅谈最长上升子序列(LIS)的更多相关文章
- 浅谈最长上升子序列(O(n*logn)算法)
今天GM讲了最长上升子序列的logn*n算法,但没讲思路... 我看了篇博客,发现-- 说的有道理!!! 首先,举例子: a[7]={1,2,4,3,6,7,5}(假设以1开头) 很明显,LIS=5: ...
- 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 ...
- 【部分转载】:【lower_bound、upperbound讲解、二分查找、最长上升子序列(LIS)、最长下降子序列模版】
二分 lower_bound lower_bound()在一个区间内进行二分查找,返回第一个大于等于目标值的位置(地址) upper_bound upper_bound()与lower_bound() ...
- 题解 最长上升子序列 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 ...
随机推荐
- Python 爬虫 NewCnblogs (爬虫-Django-数据分析)
需求分析 数据库架构 注册 登录 首页 个人站点 文章+评论 后台 爬虫 数据分析 添加搜索+已上线
- pl/sql学习(6): 引号/程序调试/列中的字符串合并/正则表达式
有关自治事务的问题: https://www.cnblogs.com/princessd8251/p/4132649.html 我在plsql development学习中遇到的常见问题: (一) 引 ...
- Postman 安装及使用入门教程(我主要使用接口测试)
1.Postman 安装及使用入门教程(我主要使用接口测试)Postman的English官网:https://www.getpostman.com/chrome插件整理的Postman中文使用教程( ...
- Linux中常用操作命令(转)
1.cd命令 这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径.如: cd /root/Docements # 切 ...
- 清除代码中的svn文件。
@echo on color 2f mode con: cols=80 lines=25 @REM @echo 正在清理SVN文件,请稍候...... @rem 循环删除当前目录及子目录下所有的SVN ...
- 微信小程序--家庭记账本开发--07
最终展示以及相关代码 1.最终效果展示 最终效果展示已经根据最初要求使用视频拍摄在抖音上,下面是相关页面展示图片: 2.相关代码 本次开发主要页面则是首页界面以及记账界面以及实现页面跳转,以及记账内容 ...
- macOS上实现Qt应用程序做文件关联打开
一.背景介绍 用Qt开发的应用程序要实现文件关联,双击时用默认关联的程序打开文件,在Windows上这个功能非常容易实现.Windows应用程序在安装的时候可以在注册表中写入相关的键值对.打开文件的时 ...
- .Net Core WebAPI 搭建
.Net Core WebAPI 搭建 1.创建项目 使用开发工具为 Visual Studio 2017 2.创建 Controller 实体类 public class Book { public ...
- ISP PIPLINE (五) Denoise
what is the Denoise? Denoise就是图像去噪,平滑图像,并保留图像细节. why does Denoise? 图像在采集并转换为数字信号的过程会引入一些噪声,这些噪声会让图片看 ...
- java 图片裁剪
图片裁剪功能,我一直以为是前端那边去做,后台不用做过多的考虑,现在我发现,前端去做裁剪好像不是太理想,我在这里简单地介绍一下我们大java的裁剪功能 前端只需要上传,x (x轴),y(y轴) , h( ...