最长上升子序列(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. 03-树2 List Leaves(25 分)

    Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...

  2. FZU 2150 Fire Game (高姿势bfs--两个起点)

    Description Fat brother and Maze are playing a kind of special (hentai) game on an N*M board (N rows ...

  3. 学习.net的步骤

    第一步 学习HTML与CSS 这并不需要去学一大堆的诸如Dreamweaver,Firework之类的各种网页设计工具,关键是理解HTML网页嵌套的block结构与CSS的box模型.许多ASP.NE ...

  4. 函数————swap

    swap(vec[i],vec[j]); 交换两个元素.

  5. VC2010 CString.Format使用报错 error C2664

    error C2664: “void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)”: 不能将参数 1 ...

  6. BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)

    传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...

  7. 深入研究CSS

    通常我们在学习CSS的时候,感觉很容易掌握,却常常在实际应用中碰到各式各样难以填补的“坑”,为避免大家受到同样的困惑与不解,本文详细讲解了CSS中优先级和Stacking Context等诸多高级特性 ...

  8. djanjo中url路由匹配规则是啥意思

    一,django路由匹配规则的本质是通过正则表达式对用户的url进行匹配. 1,r 是正则表达式中防止转义的符号,例如在python/n代表换行,加上r就不换行了. 2,$ 正则表达式中表示以什么什么 ...

  9. 2019 ICPC Asia Nanchang Regional C And and Pair 找规律/位运算/dp

    题意: 给定一个二进制表示的n,让你找满足如下要求的数对(i,j)的个数 $0 \leqslant j \leqslant i \leqslant n$ $ i & n = i $ $ i & ...

  10. 2018icpc南京/gym101981 G Pyramid 找规律

    题意: 数一个金字塔里面有多少个正三角形. 题解: ans[n]=n*(n-1)*(n-2)*(n-3)/24 #include<bits/stdc++.h> using namespac ...