洛谷链接:https://www.luogu.org/problem/P1020

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是\le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式

11行,若干个整数(个数\le 100000≤100000)

输出格式

22行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入 #1复制

389 207 155 300 299 170 158 65
输出 #1复制

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导弹拦截题解的更多相关文章

  1. 洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理

    题目链接:https://www.luogu.com.cn/problem/P1020 题目大意: 给你一串数,求: 这串数的最长不上升子序列的长度: 最少划分成多少个子序列是的这些子序列都是不上升子 ...

  2. codevs1044 拦截导弹==洛谷 P1020 导弹拦截

    P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天 ...

  3. 洛谷 P1020 导弹拦截(dp+最长上升子序列变形)

    传送门:Problem 1020 https://www.cnblogs.com/violet-acmer/p/9852294.html 讲解此题前,先谈谈何为最长上升子序列,以及求法: 一.相关概念 ...

  4. codevs——T1044 拦截导弹 || 洛谷——P1020 导弹拦截

    http://codevs.cn/problem/1044/ || https://www.luogu.org/problem/show?pid=1020#sub 时间限制: 1 s  空间限制: 1 ...

  5. 洛谷P1020 导弹拦截【单调栈】

    题目:https://www.luogu.org/problemnew/show/P1020 题意: 给定一些导弹的高度. 一个导弹系统只能拦截高度不增的一系列导弹,问如果只有一个系统最多能拦截多少导 ...

  6. 洛谷P1020 导弹拦截

    n²谁都会打,不说了. 这里讨论一下nlogn算法(单调不减): 首先开始考虑单调性,我习惯性的以为是单调队列/栈优化的那个套路,想要找到一个跟下标有关的单调性却发现没有. 例如:我想过当下标增加时f ...

  7. 洛谷P1020导弹拦截——LIS

    题目:https://www.luogu.org/problemnew/show/P1020 主要是第二问,使用了dilworth定理:一个序列中最长不上升子序列的最大覆盖=最长上升子序列长度. di ...

  8. 洛谷 - P1020 - 导弹拦截 - 最长上升子序列

    https://www.luogu.org/problemnew/show/P1020 终于搞明白了.根据某定理,最少需要的防御系统的数量就是最长上升子序列的数量. 呵呵手写二分果然功能很多,想清楚自 ...

  9. 洛谷 [P1020] 导弹拦截 (N*logN)

    首先此一眼就能看出来是一个非常基础的最长不下降子序列(LIS),其朴素的 N^2做法很简单,但如何将其优化成为N*logN? 我们不妨换一个思路,维护一个f数组,f[x]表示长度为x的LIS的最大的最 ...

随机推荐

  1. [转]使用apt安装nodejs10

    使用apt安装nodejs10 链接地址:https://blog.csdn.net/sunhaobo1996/article/details/80340513

  2. [LeetCode] 773. Sliding Puzzle 滑动拼图

    On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square repre ...

  3. radio和checkbox的js勾选使用

    Html: <table> <tr><th class="w1">党内职务</th><td colspan="3&q ...

  4. Java中缓存的介绍

    一.什么是缓存1.Cache是高速缓冲存储器 一种特殊的存储器子系统,其中复制了频繁使用的数据以利于快速访问2.凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之 ...

  5. ddl语法

    创建表: create table 表名 ( 字段1 varchar2(32) not null primary key, 字段2 date not null ) tablespace 表空间名 事务 ...

  6. 09 Servlet相关知识点---学习笔记

    1.概念:运行在服务器端的小程序 Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则.将来我们自定义一个类,实现Servlet接口,复写方法. 2.快速入门:(1)创 ...

  7. KAFA 监测| Kafka监测的方法和工具

    1.目标 在我们上一篇Kafka教程中,我们讨论了Kafka Tools.今天,我们将看到Kafka Monitoring.在此,我们将学习如何监控Apache Kafka的概念.此外,我们将涵盖在故 ...

  8. 《TCP/IP - OSI和TCP/IP分层模型》

    一:分层模型 -  - OSI 更强调:通信协议必要的功能是什么 - TCP/IP 更强调:在计算机上实现协议应该开发哪种程序  二:为什么会产生协议标准化 (分层模型的产生)? - 由于各个厂商生产 ...

  9. Asp.net Core CORS 跨域

    本文主要介绍在Asp.net Core采用CORS方式解决跨域 关于跨域的原理介绍可参考Asp.net Web API 解决跨域详解 1 在Startup添加允许跨域的策略 services.AddC ...

  10. [高清·非影印] 深度学习入门:基于Python的理论与实现 + 源代码

    ------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...