Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)
Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)
Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
Input
一行,若干个正整数最多100个。
Output
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
Sample Input
389 207 155 300 299 170 158 65
Sample Output
6
2
Http
Luogu:https://www.luogu.org/problem/show?pid=1020
Source
二分,贪心,最长不下降子序列,单调队列
解决思路
第一问比较容易理解,就是求最长不上升子序列。动态规划的方法可以过,但复杂度是n^2的,这里介绍另外一种方法。
首先想清楚一点,求最长不上升子序列就是求倒序的最长不下降子序列。
首先来讲一下操作吧:我们用一个vector(下面命名为Arr)来进行操作,具体如下:
从后往前扫描导弹的高度,设当前高度为x,那么若Arr为空或Arr的最后一个数比x小,则直接把x放到Arr尾部。
否则,找到第一个大于x的数,将其用x替换。
这个方法为什么是对的呢?它是基于贪心的思想,就是要使得Arr中的数尽量小(因为要求最长嘛),如果实在不行,就把Arr的长度+1,把这个数直接放到尾部。
那么关于查找操作,因为从上面的操作可以看出,我们保证了Arr的有序性,所以我们就可以用二分查找来完成。笔者这里使用的是STL中的lower_bound函数,它返回的是第一个满足大于等于x的数的位置,而因为我们这里是求最长不下降子序列,所以我们还要用一个while来找到第一个大于x的数的位置。
那么第二问怎么求呢?
其实,第二问就是求最长上升子序列的长度(正序的)。具体方法和上面一样,只是不要取等。这里讲一下为什么。
我们根据最长上升子序列的性质并结合本题特征可以知道,最长上升子序列的中的每一个元素一定就是每一个系统最后打的那一个导弹,这可以由反证法得知。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxN=200;
const int inf=2147483647;
int n;
int Height[maxN];
vector<int> Arr;
int main()
{
n=1;
while (cin>>Height[n])
n++;
n--;
Arr.clear();
vector<int>::iterator Find;
for (int i=n;i>=1;i--)//第一问,求倒序的最长不下降子序列
{
if ((Arr.size()==0)||(Arr[Arr.size()-1]<=Height[i]))//注意这里可以取等
Arr.push_back(Height[i]);
else
{
Find=lower_bound(Arr.begin(),Arr.end(),Height[i]);
while (*Find==Height[i])//这里的while是求出第一个大于Height[i]的
Find++;
*Find=Height[i];
}
}
cout<<Arr.size()<<endl;
Arr.clear();
for (int i=1;i<=n;i++)//第二问,求最长递增子序列
{
if ((Arr.size()==0)||(Arr[Arr.size()-1]<Height[i]))//注意这里不能取等
Arr.push_back(Height[i]);
else
{
Find=lower_bound(Arr.begin(),Arr.end(),Height[i]);
*Find=Height[i];
}
}
cout<<Arr.size()<<endl;
return 0;
}
Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)的更多相关文章
- 动态规划——最长不下降子序列(LIS)
最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] ...
- 动态规划 ---- 最长不下降子序列(Longest Increasing Sequence, LIS)
分析: 完整 代码: // 最长不下降子序列 #include <stdio.h> #include <algorithm> using namespace std; ; in ...
- 【动态规划】【二分】【最长不下降子序列】洛谷 P1020 导弹拦截
最长不下降子序列的nlogn算法 见 http://www.cnblogs.com/mengxm-lincf/archive/2011/07/12/2104745.html 这题是最长不上升子序列,倒 ...
- luogu P1020 导弹拦截 x
首先上题目~ luogu P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都 ...
- 洛谷 P1020 导弹拦截(dp+最长上升子序列变形)
传送门:Problem 1020 https://www.cnblogs.com/violet-acmer/p/9852294.html 讲解此题前,先谈谈何为最长上升子序列,以及求法: 一.相关概念 ...
- P1020 导弹拦截(nlogn求最长不下降子序列)
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- 【动态规划+高精度】mr360-定长不下降子序列
[题目大意] 韵哲君发现自己的面前有一行数字,当她正在琢磨应该干什么的时候,这时候,陈凡老师从天而降,走到了韵哲君的身边,低下头,对她耳语了几句,然后飘然而去. 陈凡老师说了什么呢,陈凡老师对韵哲君说 ...
- HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)
6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...
- 【题解】Luogu P2766 最长不下降子序列问题
原题传送门 实际还是比较套路的建图 先暴力dp一下反正数据很小 第一小问的答案即珂以求出数列的最长不下降子序列的长度s 考虑第二问如何做: 将每个点拆点 从前向后连一条流量为1的边 如果以它为终点的最 ...
随机推荐
- JavaScript学习要点
Javascript相关内容 1.序列化--json - stringify() 将对象转换为字符串 - parse() 将字符串转换为对象 list=[11,22,33,44,55]; 结果:(5) ...
- Kaggle 广告转化率预测比赛小结
20天的时间参加了Kaggle的 Avito Demand Prediction Challenged ,第一次参加,成绩离奖牌一步之遥,感谢各位队友,学到的东西远比成绩要丰硕得多.作为新手,希望每记 ...
- 笔试题——C++开发简单记录错误模块
题目:链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48 来源:牛客网 解析及代码来源:http ...
- dumpe2fs命令详解
基础命令学习目录首页 dumpe2fs 显示ext2.ext3.ext4文件系统的超级快和块组信息.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE ...
- Python List Comprehension
(一)使用List Comprehension的好处 在了解Python的List Comprehension之前,我们习惯使用for循环创建列表,比如下面的例子: numbers = range(1 ...
- IDEA下载插件超时的原因
setting中红框的对勾去掉就可以下载插件了
- 5233杨光--Linux第一次实验
学习计时:共14小时 读书:2小时 代码:7小时 作业:2小时 博客:3小时 一.学习目标 1. 能够独立安装Linux操作系统 2. 能够熟练使用Linux系统的基本命令 3. 熟练使用Li ...
- java 线程的简单理解
想要实现线程可以继承Thread也可以实现接口runnable,在类中重写 run()方法在主函数调用start方法就可以开辟线程. 对于java对象都有一个wait()和notify().notif ...
- GITHUB随笔 15-5月 junit
junit 是用来做单元测试的一个工具 测试是一个持续的过程.也就是说测试贯穿与开发的整个过程中,单元测试尤其适合于迭代增量式的开发过程. @ignore: 该元数据标记的测试方法在测试中会被忽 ...
- beta冲刺(7/7)
目录 组员情况 组员1:胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:何宇恒 组员11:刘一好 展示组内最新 ...