洛谷 P1020导弹拦截题解
洛谷链接:https://www.luogu.org/problem/P1020
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是\le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
11行,若干个整数(个数\le 100000≤100000)
输出格式
22行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
389 207 155 300 299 170 158 65
6
2
说明/提示
为了让大家更好地测试n方算法,本题开启spj,n方100分,nlogn200分
每点两问,按问给分
题解
这道题现在基本上已经是DP的入门问题了。
第一问实际是求一个最长不降子序列,而第二问是求最长上升子序列。
最容易理解的O(n2)的解法,而O(nlogn)的解法就费解一些了。关于这部分的原理写得最通俗易懂的是a342374071的文章:https://blog.csdn.net/a342374071/article/details/6694452。
下面先贴上O(n2)的代码。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h> using namespace std; const int MAXN = 1e5 + ;
int n = , a[MAXN], d[MAXN], dp[MAXN]; int main()
{
int ans1 = , ans2 = ;
while(scanf("%d", &a[n]) != EOF)
{
++n;
}
--n;
for(int i = ; i <= n; i++)
{
d[i] = ;
for(int j = ; j < i; j++)
{
if(a[j] >= a[i])
{
d[i] = max(d[i], d[j] + );
}
}
if(ans1 < d[i])
{
ans1 = d[i];
}
}
for(int i = ; i <= n; i++)
{
dp[i] = ;
for(int j = ; j < i; j++)
{
if(a[j] < a[i])
{
dp[i] = max(dp[i], dp[j] + );
}
}
if(ans2 < dp[i])
{
ans2 = dp[i];
}
}
cout << ans1 << endl;
cout << ans2 << endl;
return ;
}
下面是O(nlogn)的代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h> using namespace std; const int MAXN = 1e5 + ;
int n = , a[MAXN], d[MAXN], dp[MAXN], ans1 = , ans2 = , mid, l, r; int main()
{
while(scanf("%d", &a[n]) != EOF)
{
++n;
continue;
}
--n;
d[] = a[];
dp[] = a[];
ans1 = ans2 = ;
for(int i = ; i <= n; i++)
{
if(a[i] <= d[ans1])
{
ans1++;
d[ans1] = a[i];
}
else
{
l = , r = ans1;
while(l < r)
{
mid = (l + r) / ;
if(a[i] > d[mid])
{
r = mid;
}
else
{
l = mid + ;
}
}
d[l] = a[i];
}
} for(int i = ; i <= n; i++)
{
if(a[i] > dp[ans2])
{
ans2++;
dp[ans2] = a[i];
}
else
{
l = , r = ans2;
while(l < r)
{
mid = (l + r) / ;
if(a[i] <= dp[mid])
{
r = mid;
}
else
{
l = mid + ;
}
}
dp[l] = a[i];
}
}
cout << ans1 << endl;
cout << ans2 << endl;
return ;
}
这段代码中有个细节需要注意,就是当二分查找时等号应该放在if条件里,还是放在else里面。例如,在求不升子序列时,因为希望a[i]和d[mid]相等,则希望把a[i]替换d[mid]右侧的数据,这样可以使d[mid]右侧的数据尽可能大,从而使序列更长。所以程序里面的两个比较条件非常重要,如果疏忽了会导致WA。
洛谷 P1020导弹拦截题解的更多相关文章
- 洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理
题目链接:https://www.luogu.com.cn/problem/P1020 题目大意: 给你一串数,求: 这串数的最长不上升子序列的长度: 最少划分成多少个子序列是的这些子序列都是不上升子 ...
- codevs1044 拦截导弹==洛谷 P1020 导弹拦截
P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天 ...
- 洛谷 P1020 导弹拦截(dp+最长上升子序列变形)
传送门:Problem 1020 https://www.cnblogs.com/violet-acmer/p/9852294.html 讲解此题前,先谈谈何为最长上升子序列,以及求法: 一.相关概念 ...
- codevs——T1044 拦截导弹 || 洛谷——P1020 导弹拦截
http://codevs.cn/problem/1044/ || https://www.luogu.org/problem/show?pid=1020#sub 时间限制: 1 s 空间限制: 1 ...
- 洛谷P1020 导弹拦截【单调栈】
题目:https://www.luogu.org/problemnew/show/P1020 题意: 给定一些导弹的高度. 一个导弹系统只能拦截高度不增的一系列导弹,问如果只有一个系统最多能拦截多少导 ...
- 洛谷P1020 导弹拦截
n²谁都会打,不说了. 这里讨论一下nlogn算法(单调不减): 首先开始考虑单调性,我习惯性的以为是单调队列/栈优化的那个套路,想要找到一个跟下标有关的单调性却发现没有. 例如:我想过当下标增加时f ...
- 洛谷P1020导弹拦截——LIS
题目:https://www.luogu.org/problemnew/show/P1020 主要是第二问,使用了dilworth定理:一个序列中最长不上升子序列的最大覆盖=最长上升子序列长度. di ...
- 洛谷 - P1020 - 导弹拦截 - 最长上升子序列
https://www.luogu.org/problemnew/show/P1020 终于搞明白了.根据某定理,最少需要的防御系统的数量就是最长上升子序列的数量. 呵呵手写二分果然功能很多,想清楚自 ...
- 洛谷 [P1020] 导弹拦截 (N*logN)
首先此一眼就能看出来是一个非常基础的最长不下降子序列(LIS),其朴素的 N^2做法很简单,但如何将其优化成为N*logN? 我们不妨换一个思路,维护一个f数组,f[x]表示长度为x的LIS的最大的最 ...
随机推荐
- [LeetCode] 723. Candy Crush 糖果粉碎
This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...
- UE4 ios环境搭建备忘
1.windows.mac安装证书 2.安装xcode .app -- 路径可以拖入 sudo gem install xcodeproj 3.错误处理 Setting up Mono Running ...
- 淡sqlserver对like '%关键词%' 处理时的索引利用问题
说法一:百分号%通配符前置会让SQL查询不走索引,改走全表扫描.这种说法很流行 结论是错误的 事实上这种说法不太准确 通配符%前置会让SQL查找索引时效率极速下降,但在大多数情况下还是会走索引(不需要 ...
- java获取当前项目路径System.getProperty("user.dir")
System.getProperty("user.dir") 就是项目的文件夹绝对路径
- LeetCode | 152. 乘积最大子序列
原题(Medium): 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 思路: 遍历数组时且逐元素相乘时,如果遇到了0,在求乘积最大值的情况下,0左边的元素 ...
- 01-打印Hello World、变量
一.打印Hello World 下面就是我们写的打印hello world程序 在go语言中://代表单行注释,/**/代表多行注释 //单行注释 /* 多行注释 多行注释 */ package ma ...
- Wing电信平台操作方法
Wing电信平台操作文档 当前文档编制于2019/9/3 一.登陆 登陆网址 https://www.ctwing.cn/ 点击右上角控制台 点击左侧栏点击产品中心 选择需要注册的产品 二.注册设备 ...
- pythony--运算符
python运算符 运算符表达式 python运算符: 赋值运算符.算数运算符.关系运算符.逻辑运算符 python表达式: 是将不同的数据(包括变量.函数)用运算符号按一定规则连接起来的一种式子 ...
- Typora语法使用说明
目录 文本 标题 超链接 锚点 列表 引用 插入图片 脚注 代码 LaTex公式 插入表情 任务列表 高亮 注脚 文本 代码: *斜体* **粗体** ***斜体加粗体*** ~~删除线~~ < ...
- 设置session销毁时间
currentUser.getSession().setTimeout();