洛谷 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 ...
随机推荐
- java学习--第50天讲到jquery
4月4日jquery讲完了. jquery组合选择器 逗号隔开 层级选择器 父元素 子元素,直接子元素和间接子元素,空格隔开. 直接后代选择器: 父元素>子元素 选择的直接子元素 下 ...
- CI框架在辅助函数中使用配置文件中的变量
问题: 现有一个自定义的辅助函数,想要获取配置文件中的配置项(配置文件路径为application/config/config.php) 分析: 辅助函数并不是定义在一个class中,而是很多个可供外 ...
- Windows Server 2008 双网卡 断网问题 总结
实施现场的情况,一个网卡接得是聚合APN的子网,一个网卡是借得局域网. 运行一份数据收发程序,从APN网接入数据,发送给局域网,程序启动一会儿后就崩溃,此时测试网卡就Ping网关了,或者是时断时续,逐 ...
- win10总是2分钟就自动睡眠怎么办 win10系统自动休眠bug怎么解决(转)
解决方法如下: 1.右键点击开始图标,选择[运行],或者利用快捷键“win+R”打开运行窗口,win键是ctrl和alt键中间的徽标键:
- Linux常用指令-ssh
目录 ssh远程登陆 ssh免密码登陆 生成公钥和私钥 将公钥复制到其他从机 文件说明 id_rsa id_rsa.pub authorized_keys known_host SSH(远程连接工具) ...
- jQuery 簡介
jQuery:是一個js庫,可以極大地簡化編程,“寫得少做得多”. jquery的作用: 挑選元素.操作屬性.事件函數.動畫和效果.ajax: jQuery庫:google和microsoft都支持, ...
- python之字典操作
字典操作代码如下: #数据字典操作汇总 person = {'name': 'Mike', 'age': 25} print("初始的数据字典:", person) #访问字典值 ...
- 学习笔记之csrf
CBV 添加 csrf 第一种: 指定方法方面添加 装饰器 @memethod_decorator(xxx) 第二种 全部添加: 注意 在类名前: @method_decorator(xxx,name ...
- BZOJ1901Zju2112 Dynamic Rankings——树状数组套主席树
题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1 ],a[i+2]……a[j]中第k小的数是多少(1≤k ...
- JavaScript限制前端页面用户表单输入
onkeyup事件 onkeyup 事件会在键盘按键被松开时发生. 内容来源:自成e家 1.只能输入数字 <input onkeyup = "value=value.replace(/ ...