题目描述

时间限制:1.0s 内存限制:256.0MB

问题描述

   给定一个长为\(n\)的序列,求它的最长上升子序列的长度。

输入格式

   输入第一行包含一个整数\(n\)。

   第二行包含\(n\)个整数\(a_1,a_2,…,a_n\),为给定的序列。

输出格式

   输出一个非负整数,表示最长上升子序列的长度。

样例输入

 5
1 3 2 5 4

样例输出

 3

数据规模和约定

   \(0<n\leq10^5\),每个数不超过\(10^6\)。

解析

   所谓最长上升子序列,就是给定一列数,求序列中严格上升的子序列,子序列中数的位置不一定连续。

1.动态规划dp

   这是动态规划中的一个经典应用题目,动态规划的思想就是把问题分解为一些本质上还是相同问题的小问题,这些小问题的区别仅在于输入的参数不同,而每一个小问题的解都可以由比他参数更小的一些小问题的解推出,最小的小问题有显而易见的解,这被称之为边界。最长上升子序列(LIS)问题也是这样。

   \(a_i\)(\(1\leq i<n\))表示序列中第\(i\)个整数

   \(dp_i\) 表示以\(a_i\)为结尾的最长上升子序列的长度

   于是,\(dp_i\)要把\(a_i\)加到以\(a_j\)(\(1\leq j<i\))为上升子序列末尾的后面,并且符合\(a_j<a_i\),找一个最大的dp[j],然后令\(dp_i = dp_j + 1\)即求出了\(dp_i\)。

   最后在所有的\(dp_i\)中取一个最大的即为整个序列的最长上升子序列的长度。

   算法时间复杂度为\(O(n^2)\),当范围大一些的时候是有些低效的。

#include <iostream>
#include <algorithm>
using namespace std;
int a[100005], d[100006];
const int INF = 0x3f3f3f3f;
int main() {
int n; cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int maxx = -INF;
for (int i = 1; i <= n; i++) {
d[i] = 1;
for (int j = 1; j < i; j++)
if (a[j] < a[i])
d[i] = max(d[i], d[j] + 1);
maxx = max(maxx, d[i]);
}
cout << maxx << endl;
return 0;
}
2.二分搜索优化

   \(a_i\)(\(1\leq i<n\))表示序列中第\(i\)个整数

   \(dp_m\) 表示长度为\(m\)的最长公共子序列的末尾最小值

   当\(i=1\)时,\(dp_i=a_i\)。

   当\(i\)逐渐增加,每次扫过\(a_i\),因为\(dp_m\)代表长度为i的最长上升子序列的最小末尾,这可以代表一个长度为m的最长上升子序列,我们考虑可以把\(a_i\)加到哪个最长上升子序列后面构成一个长度\(+1\)的新的最长上升子序列。那么我们就可以在\(dp\)数组中寻找到\(j\)(\(1\leq j\leq m\))并且\(dp_j<a_i\leq dp_{j+1}\),把\(a_i\)加到这个数代表的序列后面:\(dp_{j+1}=a_i\)。

   因为\(dp\)数组是有序的,所以在进行寻找的时候就可以用二分搜索来进行。而当我们把\(a\)数组全部扫描完之后,\(dp\)数组中的最后一个有效的数字的位置即是我们所求的最长上升子序列的长度\(m\)。

   由于循环中的搜索变成了二分搜索,时间复杂度为\(O(log_n)\),所以整体时间复杂度是\(O(nlogn)\)。

#include <iostream>
#include <algorithm>
using namespace std;
int dp[100005], a[100005];
int b_search(int x, int l, int r) {
while (l < r) {
int mid = (r + l) / 2;
if (dp[mid] >= x) r = mid;
else l = mid + 1;
}
return l;
}
int main(int argc, char** argv) {
int n; cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
dp[i] = 0x3f3f3f3f;
}
int m = 1;
dp[1] = a[1];
for (int i = 2; i <= n; i++) {
if (a[i] > dp[m]) dp[++m] = a[i];
else {
int j = b_search(a[i], 1, m);
dp[j] = min(dp[j], a[i]);
}
}
cout << m << endl;
return 0;
}

   在第二个算法中我们可以通过在二分查找中改变“上确界”和“下确界”,以及在第一个算法中通过改变符号(“<”和“<=”或“>”、“>=”等),求出最长不下降、不上升、严格下降子序列等问题。

最长公共子序列-LIS的更多相关文章

  1. 最长公共子序列(LCS)和最长递增子序列(LIS)的求解

    一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...

  2. 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...

  3. 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)

    lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...

  4. 最长公共子序列-LCS问题 (LCS与LIS在特殊条件下的转换) [洛谷1439]

    题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出 一个数,即最长公共子序列的长度 输入样例 5 ...

  5. 最长上升子序列(LIS)与最长公共子序列(LCS)

    1.LIS : 给定一个序列,求它的最长上升子序列(n<=2000) 第一种 O(n^2): dp[i] 为以i为开头的最长上升子序列长度 code1: #include<cstdio&g ...

  6. 最长连续公共子序列(LCS)与最长递增公共子序列(LIS)

    最长公共子序列(不连续) 实际问题中也有比较多的应用,比如,论文查重这种,就是很实际的一个使用方面. 这个应该是最常见的一种了,不再赘述,直接按照转移方程来进行: 按最普通的方式就是,直接构造二维矩阵 ...

  7. 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

    最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...

  8. 【线型DP模板】最上上升子序列(LIS),最长公共子序列(LCS),最长公共上升子序列(LCIS)

    BEGIN LIS: 一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序 ...

  9. 【LCS,LIS】最长公共子序列、单调递增最长子序列

    单调递增最长子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 求一个字符串的最长递增子序列的长度如:dabdbf最长递增子序列就是abdf,长度为4   输入 ...

随机推荐

  1. 使用.NET 6开发TodoList应用(9)——实现PUT请求

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 PUT请求本身其实可说的并不多,过程也和创建基本类似.在这篇文章中,重点是填上之前文章里留的一个坑,我们曾经给TodoItem ...

  2. CAS学习笔记一:CAS 授权服务器简易搭建

    什么是CAS CAS是Central Authentication Service的缩写,中央认证服务,一种独立开放指令协议.CAS 是 耶鲁大学(Yale University)发起的一个开源项目, ...

  3. 据库自增ID用完

    Mysql里int类型是4个字节,如果有符号位的话就是[-2^31,2^31-1],无符号位的话最大值就是2^32-1,也就是4294967295. 自增ID达到上限用完了之后,分为两种情况: 如果设 ...

  4. Chapter 14 G-estimation of Structural Nested Models

    目录 14.1 The causal question revisited 14.2 Exchangeability revisited 14.3 Structural nested mean mod ...

  5. [C]郝斌C语言课程大纲及笔记

    本笔记整理于郝斌老师C语言课程,做学习参考之用. 1.[编程笔记]第一章 C语言概述 2.[编程笔记]第二章 C语言预备知识 3.[编程笔记]第三章 运算符与表达式 4.[编程笔记]第四章 流程控制 ...

  6. windows下的Python的下载与安装

    Python的下载 Python下载要去官网下载,xdm,这里是网址 www.python.org 因为是外网所以打开下载会慢一些(不要着急的说) 这是python官网界面,跟着图片去下载(因为我这会 ...

  7. Nginx部署及Web基础

    目录 Nginx部署及Web基础 Nginx简介 Nginx特点 Web服务 Web服务器软件 Nginx和Apache对比图 部署Nginx yum安装 编译安装 平滑增加Nginx模块 Nginx ...

  8. 我踩过的Django的坑

    把自己在使用Django过程中吃过的亏 踩过的坑 记录一下 1. unique_together传的是元组 正确:unique_together = (('app_id', 'module_id', ...

  9. JMeter_调试取样器(Debug Sampler)

    大家在调试 JMeter 脚本时有没有如下几种需求: 我想知道参数化的变量取值是否正确! 我想知道正则表达式提取器(或json提取器)提取的值是否正确! 我想知道 JMeter 属性! 调试时服务器返 ...

  10. 关于vue部署到nginx服务下,非根目录,刷新页面404的问题

    如果在根目录则添加 try_files $uri $uri/ /index.html; 如果不在根目录则添加,格式如下 location  /xxxx  { try_files $uri $uri/ ...