洛谷 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 ...
随机推荐
- python-lambda用法
前言: lambda函数也叫匿名函数,即,函数没有具体的名称. 一.基础 lambda语句构建的其实是一个函数对象.匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果 ...
- 先埋锅-CF-Valid BFS?-差一点没交上
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> ...
- Spring方法级别的验证
设置验证点及验证方式(1)Spring方法级别的验证有多种验证方式,比较常用的有 @NotBlank:主要是对字符串的验证,不为null且去除空白符之后长度大于0 @NotNull:主要是对对象的验证 ...
- 爬虫时http错误提示
在爬虫,请求网站的时候,有时候出现域名报错,所出现的代码所对应的意思:
- PAT L2-015 互评成绩
https://pintia.cn/problem-sets/994805046380707840/problems/994805062432309248 学生互评作业的简单规则是这样定的:每个人的作 ...
- 被深信服上网行为管理器AC拒绝的操作如何正常访问
1.管理员登入帐号 2.如下图,在菜单[实时状态]-[上网行为监控]中,搜索指定IP的行为记录,找到被拒绝的数据 3.如下图,在菜单[系统管理]-[全局排除地址]中,增加不过滤的地址并提交即可
- Windows环境搭建mysql服务器
Windows环境搭建mysql服务器: 1.下载mysql-installer-community-5.7.3.0-m13.2063434697并安装 安装详细步骤>> 2.安装mys ...
- ubunut下使用kubeadm离线安装k8s1.9
模仿转载的那个博客,简单记录下过程. 需要的文件. 原贴里面的:http://www.bladewan.com/2018/01/02/kubernetes_install/ 镜像文件,以及单独下载一些 ...
- Node 多页面请求
//功能:创建web服务器接收客户请求// http://127.0.0.1:8080/index 准备// http://127.0.0.1:8080/news 准备// public/index. ...
- Linux基础学习(1)--Linux系统简介
第一章——Linux系统简介 1.UNIX和Linux发展史: 1.1 unix发展史: (1)1965年,美国麻省理工学院(MIT).通用电气公司(GE)及AT&T的贝尔实验室联合开发Mul ...