洛谷 P1020 导弹拦截(dp+最长上升子序列变形)
参考资料:
[1]:LIS详解1
[2]:LIS详解2
相关概念解释:
1.串 & 子序列
一个串的子串是指该串的一个连续的局部。
如果不要求连续,则可称为它的子序列。
比如对串: "abcdefg" 而言,"ab","abd","bdef" 等都是它的子序列。
特别地,一个串本身,以及空串也是它的子序列。
2.最长上升子序列 & 最长不下降子序列
最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。
而最长不下降子序列则不一定要保证单调递增,只要保证 a[ i ] <= a[ j ] ( j > i , 且在序列范围内)即可。
现在开始回归主题:
题意:
中文题意,不再赘述;
题解:
第一问求最长不上升子序列的长度;
第二问求这个序列里面最少有多少最长不上升子序列。
难点就在与第二问,如何求呢?
看大佬博客说“求一个序列里面最少有多少最长不上升序列等于求这个序列里最长上升序列的长度”,我也不懂为啥 /小纠结,或许,这就是大佬吧。
废话少说,上AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=1e5+; int n;
int a[maxn];
int dp[maxn]; void Solve()
{
int len=;
dp[len]=INF;
for(int i=;i <= n;++i)
{
if(a[i] <= dp[len])
dp[++len]=a[i];
else
{
int l=,r=len+;
while(r-l > )//二分出最后一个不小于 a[i] 的下标
{
int mid=(l+r)/;
if(dp[mid] >= a[i])//注意,此处取到"=="判给了 l
l=mid;
else
r=mid;
}
dp[r]=a[i];
}
}
printf("%d\n",len);
len=;
dp[len]=-;
for(int i=;i <= n;++i)//求最长上升子序列
{
if(a[i] > dp[len])
dp[++len]=a[i];
else
{
int t=lower_bound(dp+,dp+len+,a[i])-dp;
dp[t]=a[i];
}
}
printf("%d\n",len);
} int main()
{
while(~scanf("%d",&a[++n]))//以回车结束输入的输入方式
continue;
n--;
Solve();
}
bug:
(1):输入方式
正确的输入方式:
while(~scanf("%d",&a[++n]))//以回车结束输入的输入方式
continue;
n--;//最后一个 n 接受的是 '\n' ,所以需要减去错误的输入方式,返回 RE,至今不知道为啥,有知道的大佬可否告知一二%%%%%%%%
do
{
scanf("%d",&a[++n]);
}while(getchar() != '\n');第一种输入方式在本地无法测试,但 OJ 可以。
第二种输入方式,虽然本地可以测试,但提交后返回 RE,应该是输入停不下来的吧。
分割线:2019.6.3
对第二问有了深一步的理解;
第二问求得是最少需要多少导弹拦截系统,根据贪心的思想,每个导弹系统都希望可以拦截尽可能多的导弹;
那么第一个导弹拦截系统最多可以拦截 cnt1 个,cnt1 = 最长不上升子序列的长度;
第二个导弹拦截系统最多可拦截 cnt2 个,cnt2 = 去掉第一次拦截的导弹后的最长不上升子序列的长度;
.............
第x个导弹拦截系统最多可拦截 cntx 个,cntx = 去掉前(x-1)次拦截的导弹后的最长不上升子序列长度;
假设第一次拦截的最低的导弹高度为 a1;
第二次拦截的最低的导弹高度为 a2;
..............
第x次拦截的最低导弹高度为 ax;
那么,a1 < a2 < ... < ax;
用反证法证明:
假设 ai > aj ( i<j );
那么,在第 i 次拦截中结尾的不应该是 ai,而应该是比 ai 还小的 aj;
但已经假设 ai 是第 i 次拦截中的最低导弹高度,与假设矛盾;
所以,第二问求的是最长上升子序列;
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=1e5+; int n;
int a[maxn];
int tmp[maxn];
int d[maxn]; void Solve()
{
int k=n;
for(int i=;i <= n;++i)
tmp[i]=a[k--]; int cnt=;
d[cnt]=-;
for(int i=;i <= n;++i)
{
if(tmp[i] >= d[cnt])
d[++cnt]=tmp[i];
else
{
int t=upper_bound(d+,d+cnt+,tmp[i])-d;
d[t]=tmp[i];
}
}
printf("%d",cnt); cnt=;
for(int i=;i <= n;++i)
{
if(a[i] > d[cnt])
d[++cnt]=a[i];
else
{
int t=lower_bound(d+,d+cnt+,a[i])-d;
d[t]=a[i];
}
}
printf(" %d\n",cnt); return ;
}
int main()
{
// freopen("C:/Users/14685/Desktop/stdin&&stdout/contest","r",stdin);
n=;
while(~scanf("%d",&a[++n]));
n--;
Solve(); return ;
}
洛谷 P1020 导弹拦截(dp+最长上升子序列变形)的更多相关文章
- codevs1044 拦截导弹==洛谷 P1020 导弹拦截
P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天 ...
- 洛谷 - P1020 - 导弹拦截 - 最长上升子序列
https://www.luogu.org/problemnew/show/P1020 终于搞明白了.根据某定理,最少需要的防御系统的数量就是最长上升子序列的数量. 呵呵手写二分果然功能很多,想清楚自 ...
- 【动态规划】【二分】【最长不下降子序列】洛谷 P1020 导弹拦截
最长不下降子序列的nlogn算法 见 http://www.cnblogs.com/mengxm-lincf/archive/2011/07/12/2104745.html 这题是最长不上升子序列,倒 ...
- 洛谷 P1020导弹拦截题解
洛谷链接:https://www.luogu.org/problem/P1020 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到 ...
- 洛谷P1020 导弹拦截【单调栈】
题目:https://www.luogu.org/problemnew/show/P1020 题意: 给定一些导弹的高度. 一个导弹系统只能拦截高度不增的一系列导弹,问如果只有一个系统最多能拦截多少导 ...
- codevs——T1044 拦截导弹 || 洛谷——P1020 导弹拦截
http://codevs.cn/problem/1044/ || https://www.luogu.org/problem/show?pid=1020#sub 时间限制: 1 s 空间限制: 1 ...
- 洛谷P1020导弹拦截——LIS
题目:https://www.luogu.org/problemnew/show/P1020 主要是第二问,使用了dilworth定理:一个序列中最长不上升子序列的最大覆盖=最长上升子序列长度. di ...
- 洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理
题目链接:https://www.luogu.com.cn/problem/P1020 题目大意: 给你一串数,求: 这串数的最长不上升子序列的长度: 最少划分成多少个子序列是的这些子序列都是不上升子 ...
- 洛谷 P1020 导弹拦截
题目传送门 解题思路: 其实就是求一遍最长不上升子序列和最长上升子序列 AC代码: #include<iostream> #include<cstdio> #include&l ...
随机推荐
- 成功安装的Sublime Text3
安装指南 1:下载官网:https://www.sublimetext.com/3 2:安装指南:https://jingyan.baidu.com/article/b0b63dbfe1b8ff4a4 ...
- Pair Work:电梯调度算法的实现和测试 by 12061171 and 12061168
结队成员简介: 成员:牛强,学号12061171:刘文乔,学号120611683 我们之所以结对编程以完成所给课设要求,是因为我们互相了解彼此,能够更好更快地完成.下图是我们合作编程时的留影: 牛强是 ...
- 网络:Xen理解
Xen是由剑桥大学计算机实验室开发的一个开源项目.是一个直接运行在计算机硬件之上的用以替代操作系统的软件层,它能够在计算机硬件上并发的运行多个客户操作系统(Guest OS). 一.Xen虚拟化类型 ...
- <<浪潮之巅>>阅读笔记一
第一次的阅读就想读这本书的,却因为很多愿意一直拖到现在,因为听说这本书在李开复先生 的微博上有推荐,更是增加了我的阅读兴趣.可能是因为在网上找的电子版的原因,通篇阅读的速度很快,但是没有纸质数那种细嚼 ...
- jsp的自定义标签
1.相对于JSTL或Spring等第三方标签库而言的,用来实现项目中特定的功能需求. 2.自定义标签基本的组成部分 ①页面上看得见的部分 [1]通过taglib引入标签库 [2]标签本身 ②xxx.t ...
- A Survey of Machine Learning Techniques Applied to Software Defined Networking (SDN): Research Issues and Challenges
将机器学习用到SDN中的综述:研究的问题和挑战 从流量分类.路由优化.服务质量(Qos)/体验质量(QoE)预测.资源管理和安全性的角度,回顾了机器学习算法如何应用于SDN领域. 相关知识 在SDN中 ...
- mysql 备份数据库 mysqldump
@echo off for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE ...
- PGSQL 获取数据库大小以及表达小等的SQL
SELECT d.datname AS Name, pg_catalog.pg_get_userbyid(d.datdba) AS Owner, CASE WHEN pg_catalog.has_da ...
- pandas基本操作2
1.axes返回标签列表 import pandas as pd import numpy as np dates = pd.date_range(', periods=8) df = pd.Data ...
- Java基础总结(一)
1:程序执行是有顺序的,如果没有流程控制语句,执行顺序是从上到下, 2:对象没有引用指向他的时候,jvm虚拟机就会在合适的时候去清理内存垃圾 3:对象的引用就相当于方向盘,操作对象 4:java8大基 ...