洛谷 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 ...
随机推荐
- 浏览器数据库 IndexedDB 入门
一.概述 随着浏览器的功能不断增强,越来越多的网站开始考虑,将大量数据储存在客户端,这样可以减少从服务器获取数据,直接从本地获取数据. 现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的 ...
- Scrum Meeting NO.7
Scrum Meeting No.7 1.会议内容 经过老师提醒,我们认识到,应尽快把主要功能实现,其他的细枝末节应在这之后慢慢添加.当今最重要的任务是和online组和数据处理组实现数据共享. 此外 ...
- 《linux内核设计与实现》第四章
调度程序负责决定哪个进程投入运行,何时运行以及运行多长时间.只有通过调度程序合理调度,系统资源才能最大限度发挥作用,多进程才会有并发执行的效果. 最大限度地利用处理器时间的原则是,只要有可以执行的进程 ...
- Leetcode——58.最后一个单词的长度
给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度. 如果不存在最后一个单词,请返回 0 . 说明:一个单词是指由字母组成,但不包含任何空格的字符串. 示例: 输入: &quo ...
- JProfiler的使用
1.下载地址:http://www.ej-technologies.com/download/jprofiler/files 2.使用过程 1.点击此图的new Session 2.点击左边appli ...
- Mybatis复杂嵌套关联一例
Mybatis three entity relation:association in collection PatentMapper.xml <resultMap id="Bas ...
- ODBC 驱动程序管理器 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配 解决方案
程序报错如下: ---------------------------Microsoft 数据链接错误---------------------------测试连接失败,因为初始化提供程序时发生错误. ...
- linux_修改文件权限chmod 、改变文件/目录所有者chown
chmod使用事例 数字方法 chmod -R 751 [FILE] ugoa方法 chmod -R u=wrx,g=rx,o=x [FILE] 说明 chmod [OPTION] [MODE] [F ...
- C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...
- matplotlib绘图pie
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/5/28 16:05 # @Author : zhang chao # @Fi ...