[tem]最长上升子序列
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行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
389 207 155 300 299 170 158 65
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]最长上升子序列的更多相关文章
- DP———3.最长上升子序列的和
Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. May ...
- 用python实现最长公共子序列算法(找到所有最长公共子串)
软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- LintCode 77: 最长公共子序列
public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...
- 最长下降子序列O(n^2)及O(n*log(n))解法
求最长下降子序列和LIS基本思路是完全一样的,都是很经典的DP题目. 问题大都类似于 有一个序列 a1,a2,a3...ak..an,求其最长下降子序列(或者求其最长不下降子序列)的长度. 以最长下降 ...
- 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
先要搞明白:最长公共子串和最长公共子序列的区别. 最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...
- [BZOJ3173][Tjoi2013]最长上升子序列
[BZOJ3173][Tjoi2013]最长上升子序列 试题描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...
随机推荐
- java 接口实现的概念整理
1.在java语言中接口由类实现,以便使用接口中的方法,重写接口中的方法,实现接口的类必须重写接口中的所有类,由于接口中的方法一定是 public abstract方法,所以类重写接口中的方法不仅要去 ...
- spfa+01 规划
尼玛的哪里错了.. /* 在有向图上找一个环,使结点权值和/边权和的比例值最大 01规划,设比例为l,那么将每条边的权值改成a[u]-l*w,如果有正权环,则比例l可行 如何判图中存在正权环?将 权值 ...
- noip 初赛复习重点知识点
一.进制转化 将k进制数转化为十进制数: 设k进制数为(abcd)k,则对应十进制数为 (小数同理,乘k的负幂次) 将十进制数转成k进制数: 设十进制数为x: t1=x/k,t2=x mod k t1 ...
- C语言将字符串转json
示例代码: #include <stdio.h> #include <string.h> #include <stdlib.h> char *strrpc(char ...
- 论文阅读笔记六:FCN:Fully Convolutional Networks for Semantic Segmentation(CVPR2015)
今天来看一看一个比较经典的语义分割网络,那就是FCN,全称如题,原英文论文网址:https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn ...
- 饮冰三年-人工智能-linux-09 服务
1:SSH服务(提供远程连接服务) 客户端使用Xshell 链接成功 加快连接速度 关闭防火墙 2:apache 服务(提供网页服务) 2.0 准备环境 关闭防火墙:service iptables ...
- Lua中assert( )函数的使用
当Lua遇到不期望的情况时就会抛出错误,比如:两个非数字进行相加:调用一个非函数的变量:访问表中不存在的值等.你也可以通过调用error函数显示的抛出错误,error的参数是要抛出的错误信息. ass ...
- mysql如何添加一个表的外键
1:创建一个父表,主键作为子表的外键: create table province( pId int primary key auto_increment, pName varchar() ); 2: ...
- [转] 【Monogdb】MongoDB的日志系统
记得前几天有个小伙伴要查看mongodb的日志,从而排查问题,可能总找不到日志放在何处,今天就系统说一下mongodb的日志系统.mongodb中主要有四种日志.分别是系统日志.Journal日志.o ...
- IO流-file
1.1 IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再把 ...