最长上升子序列(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. UNP学习 高级I/O函数

    首先为一个I/O函数设置超时,这有三种方法.然后是三个read和write函数的变体: recv和send,他们可以把含有标志的第四个参数从进程传给内核: readv和writev这两个函数可以指定一 ...

  2. 树莓派GPIO口驱动编写

    一.wiringpi写法 #include <wiringPi.h> #include <stdlib.h> int main(int argc,char *argv[]) { ...

  3. Linux下用户-组权限配置

    cat /etc/group cat /etc/ashadow 一.用户管理 1.添加用户 #useradd 用户名 useradd php100;用cat /etc/passwd查看 分析:php1 ...

  4. 2.zabbix自定义模板

    zabbix自定义模板 zbx_base_templates.xml <?xml version="1.0" encoding="UTF-8"?> ...

  5. [CSP-S模拟测试58]题解

    以后题解还是单独放吧. A.Divisors 根号筛求所有数的因子,扫一遍去重统计即可. #include<cstdio> #include<iostream> #includ ...

  6. MySQL 时间戳与日期格式的相互转换(转)

    1.UNIX时间戳转换为日期用函数: FROM_UNIXTIME() select FROM_UNIXTIME(1156219870); 输出:2006-08-22 12:11:10 2.日期转换为U ...

  7. datetime timestamp使用

    #coding=utf-8 import time import datetime def yes_time(): #获取当前时间 now_time = datetime.datetime.now() ...

  8. 购买一台阿里云云主机(CentOS)后

    系统的优化优化之前,首先查看版本信息 cat /etc/redhat-release CentOS release 6.9 (Final) 查看内核版本 uname -a Linux iZwz98ak ...

  9. c# networkcomms 3.0实现模拟登陆总结 转载https://www.cnblogs.com/zuochanzi/p/7039636.html

    最近项目需要做一个客户查询状态系统,当前上位机缺少服务功能,于是找到了networkcomms 开源框架,作为项目使用. 最新版networkcomms 下载地址:https://github.com ...

  10. 使用Microsoft.Practices.Unity 依赖注入 转载https://www.cnblogs.com/slardar1978/p/4205394.html

    Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...