最长上升子序列(LIS)问题

此处我们只讨论严格单调递增的子序列求法。

前面O(n2)的算法我们省略掉,直接进入O(nlgn)算法。

方法一:dp + 树状数组

定义dp[i]:末尾数字是i时最长上升子序列

转移方程:dp[i]=max{dp[k]|k<i}+1

代码如下:

@Frosero
#include <cstdio>
#include <iostream>
#include <cstring>
#define MAXN 100010 using namespace std; int tree[MAXN*4]; int read(int pos){
int ans = 0;
while(pos > 0){
ans = max(ans,tree[pos]);
pos -= pos & -pos;
}
return ans;
} void updata(int pos,int val){
while(pos < MAXN*4){
tree[pos] = max(tree[pos],val);
pos += pos & -pos;
}
} int a[MAXN],n,dp[MAXN],ans = 0; int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
memset(tree,0,sizeof(tree));
for(int i=0;i<n;i++){
dp[a[i]] = read(a[i] - 1) + 1;
updata(a[i],dp[a[i]]);
ans = max(ans,dp[a[i]]);
}
printf("%d\n",ans);
return 0;
}

方法二:dp + 单调队列

定义dp[i]:末尾数字是下标为i的数字时最长上升子序列

定义单调队列g[i]:上升子序列长度为i时最后一位的最小值

代码如下:

@Frosero
#include <cstdio>
#include <iostream>
#include <cstring>
#define MAXN 100010
#define INF 0x3f3f3f3f using namespace std; int a[MAXN],n,dp[MAXN],g[MAXN],ans = 0; int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<=n;i++) g[i] = INF;
for(int i=0;i<n;i++){
int k = lower_bound(g+1,g+n+1,a[i]) - g;
dp[i] = k;
g[k] = a[i];
ans = max(ans,k);
}
printf("%d\n",ans);
return 0;
}

方法三:单调队列

定义单调队列g[i]:上升子序列长度为i时最后一位的最小值

代码如下:

@Frosero
#include <cstdio>
#include <iostream>
#include <cstring>
#define MAXN 100010
#define INF 0x3f3f3f3f using namespace std; int a[MAXN],n,g[MAXN],ans = 0; int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<=n;i++) g[i] = INF;
for(int i=0;i<n;i++){
int k = lower_bound(g+1,g+n+1,a[i]) - g;
g[k] = a[i];
ans = max(ans,k);
}
printf("%d\n",ans);
return 0;
}

囧,相信大家也发现了第二个算法中dp数组事实上貌似并没有什么用了吧。但事实上他在过程中为我们维护了一些信息,在某些习题中我们恰好就要利用到他们了。

还有一点就是如果我们要寻找最长单调不减子序列,上面代码只要稍微更改一下即可,请读者自己思考吧,哈哈 ^.^ 加油!

最长上升子序列(LIS)问题的更多相关文章

  1. 2.16 最长递增子序列 LIS

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

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

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

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

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

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

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

  5. 题解 最长上升子序列 LIS

    最长上升子序列 LIS Description 给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的 ...

  6. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  7. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  8. 1. 线性DP 300. 最长上升子序列 (LIS)

    最经典单串: 300. 最长上升子序列 (LIS) https://leetcode-cn.com/problems/longest-increasing-subsequence/submission ...

  9. 最长上升子序列(LIS)模板

    最长递增(上升)子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增(上升)子序列. 考虑两个数a[x ...

  10. hdu1025 dp(最长上升子序列LIS)

    题意:有一些穷国和一些富国分别排在两条直线上,每个穷国和一个富国之间可以建道路,但是路不能交叉,给出每个穷国和富国的联系,求最多能建多少条路 我一开始在想有点像二分图匹配orz,很快就发现,当我把穷国 ...

随机推荐

  1. python学习--第二天 爬取王者荣耀英雄皮肤

    今天目的是爬取所有英雄皮肤 在爬取所有之前,先完成一张皮肤的爬取 打开anacond调出编译器Jupyter Notebook 打开王者荣耀官网 下拉找到位于网页右边的英雄/皮肤 点击[+更多] 进入 ...

  2. kvm无人值守安装centos6

    nginx配置 server { listen default_server; server_name _; root /home/iso; # Load configuration files fo ...

  3. [CSP-S模拟测试]:F(DP+线段树)

    题目传送门(内部题49) 输入格式 第一行四个整数$n,q,a,b$.接下来$n$行每行一个整数$p_i$. 输出格式 一行一个整数表示答案. 样例 样例输入: 10 3 3 7 样例输出: 数据范围 ...

  4. python学习笔记:接口开发——flask Demo实例

    举例1,返回当前时间接口 ''' 初始化:所有的Flask都必须创建程序实例, web服务器使用wsgi协议,把客户端所有的请求都转发给这个程序实例 程序实例是Flask的对象,一般情况下用如下方法实 ...

  5. gitlab搭建使用

    1.安装gitlab __环境准备__ [root@gitlab ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [r ...

  6. 慎用margin系列1---CSS的margin塌陷(collapse) 问题与对策

      对于以下简单代码: 如果您认为应该是这样的话: 那就错了.结果是这样的: 因为CSS中存在一个margin collapse,即边界塌陷或者说边界重叠.对于上下两个并列的div块而言,上面div的 ...

  7. c# dotNetBar symbol属性代码动态设置方法

    C#: button.Symbol = "\uf060"; VB: button.Symbol = ChrW("&Hf060") Since we in ...

  8. 38-python基础-python3-检查字典中是否存在键或值

    in 和 not in 操作符   请注意, 在前面的例子中,‘name’ in spam 本质上是一个简写版本.相当于'name' in spam.keys()

  9. CF1158C

    题意:有排列p, 令\(nxt_i\)为\(p_i\)右侧第一个大于\(p_i\)的数的位置,若不存在则\(nxt_i=n+1\) 现在整个p和nxt的一部分丢失了,请根据剩余的nxt,构造出一个符合 ...

  10. BUUCTF PWN部分题目wp

    pwn好难啊 PWN 1,连上就有flag的pwnnc buuoj.cn 6000得到flag 2,RIP覆盖一下用ida分析一下,发现已有了system,只需覆盖RIP为fun()的地址,用peda ...