一、瞎扯的内容

给一个长度为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]);
} }

三、来道题

洛谷P1439

题目简述:给出两个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)的更多相关文章

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

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

  2. 2.16 最长递增子序列 LIS

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

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

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

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

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

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

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

  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. HTML5 图片下载

    1. 概述 1.1 说明 在项目过程中,有时候需要下载某一展示图片,html5中定义了<a> download属性,download属性规定被下载的超链接目标,该属性可以设置一个值来规定下 ...

  2. iOS -- Effective Objective-C 阅读笔记 (7)

    1: 实现 description 方法 NSlog 在输出自定义的类时, 只输出了 类名 和 对象的内存地址. 要想输出更为有用的信息也很简单, 只需要覆写 description 方法并将描述此对 ...

  3. python第10天(上)

    multiprocessing包是Python中的多进程管理包.与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程.该进程可以运行在Py ...

  4. 利用fastjson解析json并通过js&ajax实现页面的无跳转刷新

    1.json是一种优秀的数据格式,在移动开发和web开发中经常用到,本例中通过一个小案例讲解如何通过alibaba的开源框架fastjson来解析jason数据格式并通过js实现无跳转刷新 2,新建一 ...

  5. Eclipse中如何将项目转成Dynamic Web项目

    项目接手前的同事是使用MyEclipse写的,拿SVN将项目导入eclipse时,web项目就会变成java项目,这时就需要修改配置文件将项目转成web,步骤如下: 1.修改项目配置文件. 要修改的项 ...

  6. Vue学习陷阱

    v-for在嵌套时index没办法重复用,内循环与外循环不能共用一个index <swiper-item v-for="(items,index) in swiperList" ...

  7. 安装Hive过程中报错:Unsupported major.minor version 52.0

    在安装hive的过程中,我觉得我是按照教程走的,但是在启动hive时还是报错了,错误如下 Exception in thread "main" java.lang.Unsuppor ...

  8. Pok 使用指南

    Pok 使用指南 POK 是一个开源的符合ARINC653的操作系统,因为一些原因,我要开始接触一个全新的领域,再此希望记录下每天点滴进步,同时也欢迎指正吧. 目前先简单说明POK的使用指南 获取源码 ...

  9. Python网络数据采集PDF

    Python网络数据采集(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/16c4GjoAL_uKzdGPjG47S4Q 提取码:febb 复制这段内容后打开百度网盘手 ...

  10. jmeter--接口自动化jmeter+ant+jenkins

    的 一.介绍 接口自动化工具:jmeter+ant+jenkins 流程: -1.jmeter已录制或手动设置好脚本后 -2.配置ant,使用Ant工具,进行批量执行jmeter的脚本 -3.使用Je ...