洛谷千题详解 | P1020 [NOIP1999 普及组] 导弹拦截【C++语言】

news2024/12/23 6:32:19

博主主页:Yu·仙笙

专栏地址:洛谷千题详解

 

目录

题目描述

输入格式

输出格式

输入输出样例

 解析:

C++源码:

C++源码2:


--------------------------------------------------------------------------------------------------------------------------------

 --------------------------------------------------------------------------------------------------------------------------------

题目描述

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

输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

 --------------------------------------------------------------------------------------------------------------------------------

输入格式

一行,若干个整数,中间由空格隔开。

 --------------------------------------------------------------------------------------------------------------------------------

输出格式

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

 --------------------------------------------------------------------------------------------------------------------------------

输入输出样例

输入 #1

389 207 155 300 299 170 158 65

输出 #1

6
2

 --------------------------------------------------------------------------------------------------------------------------------

 解析:

将拦截的导弹的高度提出来成为原高度序列的一个子序列,根据题意这个子序列中的元素是单调不增的(即后一项总是不大于前一项),我们称为单调不升子序列。本问所求能拦截到的最多的导弹,即求最长的单调不升子序列

考虑记 dpi​ 表示「对于前 i 个数,在选择第 ii 个数的情况下,得到的单调不升子序列的长度最长是多少」。于是可以分两种情况:

  • 第 i 个数是子序列的第一项。则 1dpi​←1。
  • 第 i 个数不是子序列的第一项。选择的第 i个数之前选择了第 j个数。根据题意,第 j 个数的值h(j) 应当小于第 i 个数的值 h(i)。枚举这样的 j,可以得到状态转移方程:

dpi​=j<i,h(j)≥h(i)max​{dpj​+1}

综合这两种情况,得到最终的状态转移方程:

dpi​=max{1,j<i,h(j)≥h(i)max​{dpj​+1}}

值得注意的是,第 n 个数不一定是最长单调不升子序列的最后一项。为了求出答案,我们需要枚举最后一项是哪个:

ans=1≤i≤nmax​{dpi​}

直接枚举进行状态转移,时间复杂度显然是O(n^2)。 下面考虑优化。

记 f_i表示「对于所有长度为 i 的单调不升子序列,它的最后一项的大小」的最大值。特别地,若不存在则 f_i=0。下面证明:

  • 随 i 增大,f_i​ 单调不增。即fi​≥fi+1​。

考虑使用反证法。假设存在 u<v,满足 fu​<fv​。考虑长度为 v 的单调不升子序列,根据定义它以 f_v 结尾。显然我们可以从该序列中挑选出一个长度为 u 的单调不升子序列,它的结尾同样是 f_v​。那么由于 fv​>fu​,与 f_u 最大相矛盾,得出矛盾。

因此 f_i 应该是单调不增的。

现在考虑以i 结尾的单调不升子序列的长度的最大值_idpi​。由于我们需要计算所有满足 h(j)>h(i) 的 jj 中,jdpj​ 的最大值,不妨考虑这个jdpj​ 的值是啥。设j=xdpj​=x,那么如果 h(i)> f_xh(i)>fx​,由于 f_x\ge h(j)fx​≥h(j),就有 h(i)>h(j)h(i)>h(j),矛盾,因此总有 h(i)\le f_xh(i)≤fx​。

根据刚刚得出的结论,f_ifi​ 单调不增,因此我们要找到尽可能大的 x 满足 h(i)≤fx​。考虑二分。

绿色区域表示合法的 f_xfx​(即 f_x\ge h(i)fx​≥h(i)),红色区域表示不合法的 f_xfx​(即 f_x< h(i)fx​<h(i)),我们需要找到红绿之间的交界点。

假设二分区域为 [l,r)[l,r)(注意开闭区间。图上黄色区域标出来了二分区域内实际有效的元素)。每次取 m=\frac{l+r}{2}m=2l+r​,如果 f_mfm​ 在绿色区域内,我们就把 ll 移动到此处(l\gets ml←m);否则把 rr 移动到此处(r\gets mr←m)。

当 r-l=1r−l=1 时,ll 处位置即为我们需要找的位置。转移 \mathit{dp}_i\gets l+1dpi​←l+1 即可。记得更新 ff。但是我们只用更新 f_{\mathit{dp}_i}fdpi​​,这是因为 f_1,f_2,\cdots f_{\mathit{dp_i}-1}f1​,f2​,⋯fdpi​−1​ 的大小肯定都是不小于 h(i)h(i) 的。f_{\mathit{dp}_i}fdpi​​ 是最后一个不小于 h(i)h(i) 的位置,f_{\mathit{dp}_i+1}fdpi​+1​ 则小于 h(i)h(i)。

时间复杂度 \mathcal O(n\log n)O(nlogn),可以通过该问。

第二问

考虑贪心。

从左到右依次枚举每个导弹。假设现在有若干个导弹拦截系统可以拦截它,那么我们肯定选择这些系统当中位置最低的那一个。如果不存在任何一个导弹拦截系统可以拦截它,那我们只能新加一个系统了。

假设枚举到第 ii 个导弹时,有 mm 个系统。我们把这些系统的高度按照从小到大排列,依次记为 g_1,g_2,\cdots g_mg1​,g2​,⋯gm​。容易发现我们就是要找到最小的 g_xgx​ 满足 g_x\ge h_igx​≥hi​(与第一问相同,这是可以二分得到的),然后更新 g_xgx​ 的值。更新之后,g_1,g_2\cdots g_xg1​,g2​⋯gx​ 显然还是单调不增的,因此不用重新排序;如果找不到符合要求的导弹拦截系统,那就说明 g_m<h_igm​<hi​,直接在后头增加一个就行。

时间复杂度 \mathcal O(n\log n)O(nlogn),可以通过该问。

--------------------------------------------------------------------------------------------------------------------------------

C++源码:

#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
const int MAXN=1e5+3;
int n,t,H[MAXN],F[MAXN];
int main(){
    while(~scanf("%d",&H[++n])); --n;
    t=0,memset(F,0,sizeof(F)),F[0]=INF;
    up(1,n,i){
        int l=0,r=t+1; while(r-l>1){
            int m=l+(r-l)/2;
            if(F[m]>=H[i]) l=m; else r=m;
        }
        int x=l+1;  // dp[i]
        if(x>t) t=x; F[x]=H[i];
    }
    printf("%d\n",t);
    t=0,memset(F,0,sizeof(F)),F[0]=0;
    up(1,n,i){
        int l=0,r=t+1; while(r-l>1){
            int m=l+(r-l)/2;
            if(F[m]<H[i]) l=m; else r=m;
        }
        int x=l+1;
        if(x>t) t=x; F[x]=H[i];
    }
    printf("%d\n",t);
    return 0;
}

-------------------------------------------------------------------------------------------------------------------------------- 

C++源码2:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 1000010
using namespace std;
typedef long long ll;
ll a[maxn],n=1,dp1[maxn],dp2[maxn],len1,len2;
inline void write(ll x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
int main(){
	while(cin>>a[n]){
		n++;
	}
	n--,len1=1,len2=1;
	dp1[1]=a[1],dp2[1]=a[1];
	for(ll i=2;i<=n;i++){
		if(a[i]<=dp1[len1]){
			dp1[++len1]=a[i];
		}
		else{
			ll k1=upper_bound(dp1+1,dp1+len1+1,a[i],greater<ll>())-dp1;
			dp1[k1]=a[i]; 
		}
		if(a[i]>dp2[len2]){
			dp2[++len2]=a[i];
		}
		else{
			ll k2=lower_bound(dp2+1,dp2+len2+1,a[i])-dp2;
			dp2[k2]=a[i];
		}
	}
	write(len1);
	puts("");
	write(len2);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99972.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【(C语言)数据结构奋斗100天】栈和队列

前言 &#x1f3e0;个人主页&#xff1a;泡泡牛奶 &#x1f335;系列专栏&#xff1a;[C语言] 数据结构奋斗100天 本期所介绍的是栈和队列&#xff0c;那么什么是栈呢&#xff0c;什么是队列呢&#xff1f;在知道答案之前&#xff0c;请大家思考一下下列问题&#xff1a; 你如何…

【问答篇】Java 线程篇 面试题(二)

每天进步一点~ (ps: 文章内容及图片出处来自本人公众号~) 01、问&#xff1a;请谈谈你对线程声明周期的6种状态的认识和理解 答&#xff1a;很多地方说线程有5种状态&#xff0c;但实际上是6种状态:NEW、RUNNABLE, BLOCKED、 WAITING、TIMED_WAITING、TERMINATED; 新创建&a…

(附源码)Springboot掌上博客系统 毕业设计 063131

Springboot掌上博客系统的设计与实现 摘 要 掌上博客系统是当今网络的热点&#xff0c;博客技术的出现使得每个人可以零成本、零维护地创建自己的网络媒体&#xff0c;Blog站点所形成的网状结构促成了不同于以往社区的Blog文化&#xff0c;Blog技术缔造了“博客”文化。 本文课…

微服务框架 SpringCloud微服务架构 服务异步通讯 53 MQ 集群 53.1 集群分类 53.2 普通集群

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 服务异步通讯 文章目录微服务框架服务异步通讯53 MQ 集群53.1 集群分类53.1.1 集群分类53.2 普通集群53.2.1 普通集群53.2.2 搭建普通 集群5…

2022 FIFA World Cup Final

我希望梅西能够捧杯&#xff0c;因为我怕再看见那个眼神&#xff01;写在总决赛开始前 12/18/2022 22:04 在一个周日的晚上收到了邹总发的活动信&#xff0c;我记得还在CSDN问答区在回答问题&#xff0c;突然看见私信的红点&#xff0c;其实看到活动&#xff08;活动链接点击这…

万字长文,彻底搞懂分布式缓存Redis

最近系统性地整理了Redis的知识点&#xff0c;在此和大家做些分享&#xff0c;希望能帮助到大家。 为什么Redis这么受欢迎 时代产物 随着互联网规模的不断扩张&#xff0c;越来越多的企业在技术架构上会采用分布式架构&#xff0c;而且对于系统的吞吐量以及响应速率的要求也…

非零基础自学Golang 第11章 文件操作 11.2 文件基本操作 11.2.3 文件写入 11.2.4 删除文件

非零基础自学Golang 文章目录非零基础自学Golang第11章 文件操作11.2 文件基本操作11.2.3 文件写入11.2.4 删除文件第11章 文件操作 11.2 文件基本操作 11.2.3 文件写入 与之前的文件读取相比&#xff0c;向文件写入内容也有两个接口&#xff0c;分别为Write和WriteAt。 fu…

数据管理篇之元数据

第12章 元数据 1.元数据概述 元数据定义 元数据是关于数据的数据。按照用途可以分为两类&#xff1a; 技术元数据 业务元数据 阿里巴巴常见的技术元数据&#xff1a; 分布式计算系统存储元数据 分布式计算系统运行元数据 数据开发平台中数据同步&#xff0c;计算任务、任务调…

【编译原理】第四章部分课后题答案

第 四 章 课 后 习 题 T 4.1 根据表4.1的语法制导定义&#xff0c;为输入表达式5∗(4∗32)5*(4*32)5∗(4∗32)构造注释分析树。 T 4.2 构造表达式((a∗b)(c))((a*b)(c))((a∗b)(c))的分析树和语法树&#xff1a; &#xff08;a&#xff09;根据表4.3的语法制导定义。 &…

C++中你不知道的namespace和using的用法

目录 引言 一: 冒号作用域 二、名字控制 1 命令空间 2 命令空间的使用 三、 using的指令 1 using的声明 2 using的编译指令 引言 你是不是只认为namespace 和 using 在C中是基本的语法框架&#xff0c;但是却不知道它们的真正用法&#xff0c;看完文章你会对using和name…

计算机毕设Python+Vue校园志愿者服务系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

软件测试零基础如何快速入门 ?这里有全网最详细的学习资料

目录 前言 一、首先&#xff0c;我们要了解清楚用人部门对初级测试人员的定位&#xff1a; 二、清楚了初级测试人员需要具备的能力 三、找到正确的方向 四、最后需要做的就是储备自己的能力。 一.找本软件测试基础的书 二.写文档 三.执行测试 四.多关注技术博文 五、…

城市管理网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; “模块划分&#xff1a;公告类型&#xff0c;公告信息&#xff0c;城管信息&#xff0c;居民信息&#xff0c;设诉类型&…

工程师为微型晶体管开发新的集成路线

新南威尔士大学悉尼团队展示了高 κ 钙钛矿膜如何充当二维晶体管的绝缘体 新南威尔士大学悉尼分校的研究人员开发了一种微小、透明且灵活的材料&#xff0c;可用作晶体管中的新型电介质&#xff08;绝缘体&#xff09;组件。 最近发表在《自然》杂志上的研究“高 κ 钙钛矿膜…

面试题61. 扑克牌中的顺子

晚上做了道题&#xff0c;写完看了大佬的题解发现自己很蠢&#xff0c;思维不够光想着模拟了&#xff0c;来回考虑细节磕磕绊绊写完这么一道题。虽然也是写出来了&#xff0c;复杂度都是ok的&#xff0c;不过代码长&#xff0c;处理细节麻烦。 记录一下这道题 从若干副扑克牌中…

对DataFrame的列标签增加后缀的DataFrame.add_suffix()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 为DataFrame的列标签增加后缀 DataFrame.add_suffix() [太阳]选择题 关于以下python代码说法错误的一项是? import pandas as pd df pd.DataFrame({"A": [1,2],"B":[1…

基于Unity整合BEPUphysicsint物理引擎实战

上一节我们详细的讲解BEPUphysicsint 的物理事件。此物理引擎会产生了碰撞事件与非碰撞事件&#xff0c;碰撞事件大家好理解&#xff0c;非碰撞事件例如: 物理Entity的update事件,Entity的activation/deactivation事件等。本节课来实战如何编译BEPUphysicsint源码到自己的项目,…

Linux 服务器数据同步利器

一、简介 1 认识 Rsync&#xff08;remote synchronize&#xff09;是一个远程数据同步工具&#xff0c;可通过LAN/WAN快速同步多台主机间的文件。Rsync使用所谓的“Rsync算法”来使本地和远 程两个主机之间的文件达到同步&#xff0c;这个算法只传送两个文件的不同部分&#x…

【毕业设计_课程设计】基于机器视觉的害虫种类及数量检测(源码+论文)

文章目录0 项目说明1 研究目的2 研究内容及结论3 文件介绍4 论文目录5 项目源码0 项目说明 基于机器视觉的害虫种类及数量检测 提示&#xff1a;适合用于课程设计或毕业设计&#xff0c;工作量达标&#xff0c;源码开放 1 研究目的 研究的目的在于建立一套远程病虫害自动识别…

UNION 和 UNION ALL

合并查询结果 利用UNION关键字&#xff0c;可以给出多条SELECT语句&#xff0c;并将它们的结果组合成单个结果集。合并时&#xff0c;两个表对应的列数和数据类型必须相同&#xff0c;并且相互对应。 各个SELECT语句之间使用UNION或UNION ALL关键字分隔。 语法格式 SELECT c…