浅谈最长上升子序列(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 ...
随机推荐
- Mysql -- 外键的变种 三种关系
一.介绍 因为有foreign key的约束, 使得两张表形成了三种关系 多对一 多对多 一对一 二.如果找出两张表之间的关系 #.先站在左表的角度去找 是否左表的多条记录可以对应右 ...
- 【原创】大叔问题定位分享(11)Spark中对大表子查询加limit为什么会报Broadcast超时错误
当两个表需要join时,如果一个是大表,一个是小表,正常的map-reduce流程需要shuffle,这会导致大表数据在节点间网络传输,常见的优化方式是将小表读到内存中并广播到大表处理,避免shuff ...
- 【原创】大叔问题定位分享(9)oozie提交spark任务报 java.lang.NoClassDefFoundError: org/apache/kafka/clients/producer/KafkaProducer
oozie中支持很多的action类型,比如spark.hive,对应的标签为: <spark xmlns="uri:oozie:spark-action:0.1"> ...
- docker hub加速访问设置
前言:docker是国外的,虽然有个版本开源免费,但是其docker hub还是在国外,刚刚安装后,拉镜像就会发现,连接请求超时,中断服务,这是因为防火墙的问题,所以要将源指向国内的知名docker ...
- Tomcat 下4个配置文件详解
Tomcat 的配置文件由4个 xml 文件构成,context.xml.web.xml.server.xml.tomcat-users.xml 这4个文件.每个文件都有自己的功能与配置方法,下列将逐 ...
- post 数据
可参照:http://www.voidcn.com/blog/Vindra/article/p-4917667.html 一.get请求 curl "http://www.baidu.com ...
- [转] NodeJS框架express的途径映射(路由)功能及控制
NodeJS框架express的路径映射(路由)功能及控制 我们知道Express是一个基于NodeJS的非常优秀的服务端开发框架,本篇CSSer将提供express框架的route和route co ...
- MVC中 jquery validate 不用submit方式验证表单或单个元素
<script src="/Scripts/jquery-1.4.4.js"></script> <script src="/Scripts ...
- C#使用FileSystemWatcher控件实现的文件监控功能示例
本文实例讲述了C#使用FileSystemWatcher控件实现的文件监控功能.分享给大家供大家参考,具体如下: FileSystemWatcher 可以使用FileSystemWatcher组件监视 ...
- Windows10 永久激活查询/激活时间查询/激活查询命令/激活码查询
1.使用 Windows + R组合快捷键打开运行命令框 运行: slmgr.vbs -dlv 命令 可以查询到Win10的激活信息,包括:激活ID.安装ID.激活截止日期等信息.看不懂的 ...