[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的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...
随机推荐
- 基于Web的漏洞利用
1.Nikto 基于Web的漏洞信息扫描 nikto 自动扫描web服务器上没有打补丁的软件,同时同时也检测驻留在服务器上的危险文件,nikto能够识别出特定的问题,检测服务器的配置问题, 检测某台主 ...
- 停止Monkey
adb shell top | grep monkey adb shell kill id
- js 浮点数相加 变成字符串 解决方案
var count = 0; count+=Number(parseFloat(value[i]['sla']).toFixed(2)); 数字相加的时候最好使用Number转换一下
- UEditor上传自定义文件夹
需求:使用UEditor上传时需要知道具体到哪个章节得图片,所以得根据Session中得文件重新定义 修改Handler类: public HttpSessionState Session {get; ...
- MySql-8.0.12 安装教程
MySql-8.0.12 安装教程随笔https://www.cnblogs.com/CrazyDemo/p/9409995.html MySQL 安装https://m.runoob.com/mys ...
- Windows Azure 搭建网络代理 Proxy
额 题目起的有点大 其实就是在 Linux 上使用代理 不过是用的 Azure 上的 Liunx 虚拟机而已 如何在 Azure 上搭建 VPN 见上篇:http://www.cnblogs.com/ ...
- select2插件 多选框动态初始化值
转自https://blog.csdn.net/yiyiwyf/article/details/53521980 上一篇讲了select2的多选和大标题设置. 这周做到了修改的功能,需要将旧数据的选项 ...
- order by 导出数据不一致的问题
转自 http://blog.csdn.net/wwwwei_csdn/article/details/78181197 前言 数据库分页是后台经常要使用的技术手段,有时候进行数据库查询会根据业务 ...
- uva 1232
题意: 建筑物在多长的部分是最高的成为该建筑物的覆盖度.求所有建筑物的覆盖度之和. 链接: https://vjudge.net/contest/202699#problem/E 题解: 这道题还是挺 ...
- 如何确定系统上的CPU插槽数量
环境 Red Hat Enterprise Linux 7 Red Hat Enterprise Linux 6 Red Hat Enterprise Linux 5 Red Hat Enterpri ...