Longest Increasing Subsequence(LIS) 一个美丽的名字

非常经典的线性结构dp

[朴素]:O(n^2)

  d(i)=max{0,d(j) :j<i&&a[j]<a[i]}+1

  直接两个for

[二分查找优化]:O(nlogn)

  g(i):d值为i的最小的a  每次更新然后lower_bound即可 [大于等于]

lower_bound
Return iterator to lower bound
Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val. The elements are compared using operator< for the first version, and comp for the second. The elements in the range shall already be sorted according to this same criterion (operator< or comp), or at least partitioned with respect to val. 函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的

没有返回最后的下一个  

g单调递增,所以可以二分

[线段树优化]:同上-----实质:二维偏序问题

-------------------------------------------------------------------------------------  

[例题]比如 NOIP2004合唱队形

题目描述

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

----------------------------------------------

正着一遍LIS,反着一遍LIS

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=,INF=1e6;
inline int read(){
int x=,f=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-; ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x;
} int n,d[N],g[N],a[N],f[N],ans=; void dp(){
for(int i=;i<=n;i++) g[i]=INF;
for(int i=;i<=n;i++){
int k=lower_bound(g+,g++n,a[i])-g;//printf("%d d\n",k);
d[i]=k;
g[k]=a[i];
}
reverse(a+,a+n+);
for(int i=;i<=n;i++) g[i]=INF;
for(int i=;i<=n;i++){
int k=lower_bound(g+,g++n,a[i])-g;//printf("%d f\n",k);
f[i]=k;
g[k]=a[i];
} }
int main() {
n=read();
for(int i=;i<=n;i++) a[i]=read(); dp();
for(int i=;i<=n;i++) ans=max(ans,f[n-i+]+d[i]-);
printf("%d",n-ans);
return ;
}

----------------------------------------------

Longest Decreasing Subsequence(LDS)   (不知道有没有这个名字)

也可以用二分,改一改,保留a最大的,找第一个小于等于的

 bool cmp(int a,int b){
return a>b;
}
void lds(){
for(int i=;i<=n;i++) g[i]=-INF;
for(int i=;i<=n;i++){
int k=lower_bound(g+,g++n,a[i],cmp)-g;
f[i]=k;
g[k]=a[i];
}
}

-----------------------------------------------

不上升,不下降

用upper_bound,找第一个大于的

 

 [例题]

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出格式

输入格式:

一行,若干个正整数。

输出格式:

2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入样例#1:

389 207 155 300 299 170 158 65
输出样例#1:

6
2
-------------------------------------------------------------------------------------------------------------------------------------------
一遍最长不上升,一遍最长上升
(数据规模很小,但是练习一下nlogn)
 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=,INF=1e7;
int n=,a[N],g[N],d[N],f[N];
bool cmp(int a,int b){
return a>b;
}
void lds(){
for(int i=;i<=n;i++) g[i]=-INF; for(int i=;i<=n;i++){
int k=upper_bound(g+,g++n,a[i],cmp)-g;
f[i]=k;
g[k]=a[i];
}
}
void lis(){
for(int i=;i<=n;i++) g[i]=INF; for(int i=;i<=n;i++){
int k=lower_bound(g,g++n,a[i])-g;
d[i]=k;
g[k]=a[i];
}
} int main(){
while(cin>>a[++n]);n--; lds();lis();
int _max=-INF;
for(int i=;i<=n;i++) _max=max(_max,f[i]);
printf("%d\n",_max); _max=-INF;
for(int i=;i<=n;i++) _max=max(_max,d[i]);
cout<<_max; }

[tem]最长上升子序列的更多相关文章

  1. DP———3.最长上升子序列的和

    Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. May ...

  2. 用python实现最长公共子序列算法(找到所有最长公共子串)

    软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...

  3. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  4. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  5. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  6. LintCode 77: 最长公共子序列

    public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...

  7. 最长下降子序列O(n^2)及O(n*log(n))解法

    求最长下降子序列和LIS基本思路是完全一样的,都是很经典的DP题目. 问题大都类似于 有一个序列 a1,a2,a3...ak..an,求其最长下降子序列(或者求其最长不下降子序列)的长度. 以最长下降 ...

  8. 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题

    先要搞明白:最长公共子串和最长公共子序列的区别.    最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...

  9. [BZOJ3173][Tjoi2013]最长上升子序列

    [BZOJ3173][Tjoi2013]最长上升子序列 试题描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...

随机推荐

  1. python(7):sympy模块

    sympy主要用于符号计算 1,基本操作 from sympy import* #from sympy import pprint #x=Symbol('x')#也可以这么单个定义 #y=Symbol ...

  2. vue自定义指令directives使用及生命周期

    生命周期 bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作. inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于docu ...

  3. 矩阵乘法的运算量计算(华为OJ)

    题目地址: https://www.nowcoder.com/practice/15e41630514445719a942e004edc0a5b?tpId=37&&tqId=21293 ...

  4. CentOS6 YUM安装MariaDB10.3.10

    1.先新增加一个MariaDB.repo vi /etc/yum.repos.d/MariaDB.repo [mariadb] name = MariaDB baseurl = http://mirr ...

  5. html5 之 local storage \sessjion storage

    转载: HTMl5的sessionStorage和localStorage html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage. sessi ...

  6. HL7消息部分笔记

    1.关于HL7标准 HL7是HealthLevel7的缩写,主要用于医疗领域不同的系统.应用之间的信息传递.规范各个系统间的信息传递格式. 2.字段含义: Z信息段: Z信息段是指与HL7第二版标准其 ...

  7. Python_set集合部分功能介绍

    set:无序集合,不能出现重复的元素 set的创建:s1=set() #访问速度快 #解决重复问题 x.add():添加一个新的元素,添加的重复的元素自动过滤掉 x.clear():清空集合 x.di ...

  8. Codeforces 758F Geometrical Progression

    Geometrical Progression n == 1的时候答案为区间长度, n == 2的时候每两个数字都可能成为答案, 我们只需要考虑 n == 3的情况, 我们可以枚举公差, 其分子分母都 ...

  9. JavaScript 组数去重demo

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  10. PHPcurl的post/get请求

    post/get请求 function getCurl($url,$data=null,$method='post',$https=true){ //1. 初始化 $ch = curl_init(); ...