一、瞎扯的内容

给一个长度为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. canvas图片与img图片的相互转换

    最近在一个项目中,遇到了一个问题,需要把生成的canvas形式的二维码转换为图片,可以长按识别,保存等.查找了一些资料归纳总结了一些知识. 默认在jq库里进行,引入jquery.qrcode.min. ...

  2. Java面试题复习笔记(数据库)

    1.数据库分类? 关系型数据库和非关系型. 常用关系型:Myspl.Oracle.SQLServer 非关系型:Redis.Hadoop.Memcache.Mogobd 2.关系数据库三范式? 范式就 ...

  3. Java Web 中使用ffmpeg实现视频转码、视频截图

    Java Web 中使用ffmpeg实现视频转码.视频截图 转载自:[ http://www.cnblogs.com/dennisit/archive/2013/02/16/2913287.html  ...

  4. ssh项目问题01,为创建数据库抛出的异常

    框架什么都搭建好了,但是一直抛出如图问题,网上资料很多让你设置时间之类的,也设置了还是继续抛异常,最后带我的师傅说没有创建数据库,我都要郁闷死了,网上那么多,很多写的都不能解决问题,还乱写,浪费别人时 ...

  5. 记一次Mysql魔鬼实训

    1.查看某个Mysql数据库当前使用的字符集 show create database [库名称] 2.查看当前书库版本信息 #mysql -V MariaDB [(none)]> use my ...

  6. spark MLlib collaborativeFilltering学习

    package ML.collaborativeFilltering; import org.apache.spark.SparkConf; import org.apache.spark.api.j ...

  7. git配置公钥

    1.在linux的命令行下,或者是windows上Git Bash命令行窗口中键入: ssh-keygen -t rsa -C "gitee.com" 2..一直按回车(Enter ...

  8. UOJ#218. 【UNR #1】火车管理 线段树 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和 ...

  9. es ik分词插件安装

    1.ik下载(下载es对应版本的ik分词包) https://github.com/medcl/elasticsearch-analysis-ik/releases 2.mac cd /usr/loc ...

  10. 堡垒机jumpserver测试记录--安装

    一步一步安装(CentOS) 基本都是官网的东西,只是有些坑做了记录. http://docs.jumpserver.org/zh/docs/step_by_step.html 环境 系统: Cent ...