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. java子类继承关系

    1.java的类按照继承关系的树形结构所有的类其根节点都是object类,一个类有两种重要的成员,一是变量 .二是方法.子类继承不能继承父类中被声明为private的变量和方法. public cla ...

  2. django----多对多数据添加

    class UserInfo(models.Model): """ 用户表:既有班主任也有老师 """ username = models. ...

  3. bzoj2200拓扑排序+最短路+联通块

    自己写的不知道哪里wa了,明明和网上的代码差不多.,. /* 给定一张图,有的边是无向边,有的是有向边,有向边不会出现在环中,且有可能是负权值 现在给定起点s,求出s到其余所有点的最短路长度 任何存在 ...

  4. vue @click 使用三目运算(实现动态更换绑定的函数)

    转载:https://www.jianshu.com/p/ea4471c9f333 @click 错误写法 @click="dialogStatus=='create'?createData ...

  5. Python获取当前时间及时间转换(datetime)

    datetime是Python处理日期和时间的标准库 获取当前时间 import datetime day = datetime.datetime.now() day2 = datetime.date ...

  6. 将labelme 生成的.json文件进行可视化的代码+label.png 对比度处理的matlab代码

    labelme_to_dataset 指令的代码实现: show.py文件 #!E:\Anaconda3\python.exe import argparse import json import o ...

  7. IDM的Google商店插件

    官方扩展链接:https://chrome.google.com/webstore/detail/idm-integration-module/ngpampappnmepgilojfohadhhmbh ...

  8. [转] 谈谈JS中的函数节流

    函数节流的目的 从字面上就可以理解,函数节流就是用来节流函数从而一定程度上优化性能的.例如,DOM 操作比起非DOM 交互需要更多的内存和CPU 时间.连续尝试进行过多的DOM 相关操作可能会导致浏览 ...

  9. 分享微信h5支付源码

    类库代码 wechatH5Pay.php <?php //use Flight; /** * 微信支付服务器端下单 * 微信APP支付文档地址: https://pay.weixin.qq.co ...

  10. 跳跃表Skip List的原理

    1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...