洛谷链接: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. docker基本排错

    遇到了一个很奇葩的问题,docker运行一个容器后,执行docker ps -a可以查看到该容器处于运行状态,但是无法进入该容器. 试着使用docker stop ID和docker kill -s ...

  2. 通过ssh登录到手机 Termux

    安装Termux Termux官网:https://termux.com/ 安装openssh 安装好Termux后,点击图标进入,依次输入以下命令. 申请读写权限 termux-setup-stor ...

  3. [LeetCode] 259. 3Sum Smaller 三数之和较小值

    Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 < ...

  4. (一)Python的特点(优点和缺点)

    Python 是一种面向对象.解释型的脚本语言,同时也是一种功能强大而完善的通用型语言.相比其他编程语言(比如 Java),Python 代码非常简单,上手非常容易. Python优点: (1)简单易 ...

  5. LeetCode 331. 验证二叉树的前序序列化(Verify Preorder Serialization of a Binary Tree) 27

    331. 验证二叉树的前序序列化 331. Verify Preorder Serialization of a Binary Tree 题目描述 每日一算法2019/5/30Day 27LeetCo ...

  6. 重新安装Eclipse的一些配置

    工欲善其事,必先利其器.工具做好调整可以让我们事半功倍. 以下设置均在window-->preferences中 1.首先修改工作空间字符集为UTF-8 2.修改字体大小 3.修改Java代码提 ...

  7. Win32API文本处理

    工程模板:https://www.cnblogs.com/eternalmoonbeam/p/10793080.html 安全的文本输出方式: 需要额外包含头文件strsafe.h 依次使用以下三个函 ...

  8. Wing电信平台操作方法

    Wing电信平台操作文档 当前文档编制于2019/9/3 一.登陆 登陆网址 https://www.ctwing.cn/ 点击右上角控制台 点击左侧栏点击产品中心 选择需要注册的产品 二.注册设备 ...

  9. PHP生成随机单词

    class GenRandWords { private static $_alphas = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', ' ...

  10. docker相关--开始使用swarm模式

    Swarm简介 Swarm是Docker的一个编排工具,参考官网:https://docs.docker.com/engine/swarm/ Swarm 模式简介 要在Swarm模式下运行docker ...