Luogu-P1020(导弹拦截)(DP,LIS ,二分优化)
Luogu-P1020(导弹拦截)(DP)
题意:
给n(n<=100000) 个数字,求最长不上升子序列的长度和最少的不上升子序列的个数。
分析:
第一问:
求最长不上升子序列有 O(n^2) 的做法,不过这里会超时。我们需要降低算法复杂度。
j
表示最长子序列的长度,然后d[i]
储存以不上升子序列长度为 i 时结尾的最大数字。
假如前 i -1 个数都已经检索完毕,已经找到了最长不上升子序列d[1]~d[j]
。
然后对于第 i 个数a[i]
- 如果
a[i]<=d[j]
那么可以添加a[i]
到当前最长不上升子序列的末尾。更新d[++j]=a[i]
。 - 如果
a[i]>d[j]
那么就要尝试把a[i]
放到这个子序列中合适的位置,然后更新它。相当于是找到了以a[i]
结尾的最长不上升子序列长度。
1 2 3 4 5 6 7 8
389 207 155 300 299 170 158 65
第一步
1
389
第二步
1 2
389 207
第三步
1 2 3
389 207 155
第四步(300 找到了 389 后面的位置,然后把207覆盖,这里为什么要覆盖呢?稍后解释)
1 2 3
389 300 155
第五步
1 2 3
389 300 299
第六步
1 2 3 4
389 300 299 170
第七步
1 2 3 4 5
389 300 299 170 158
第八步
1 2 3 4 5 6
389 300 299 170 158 65
第四步中,在原来的389 207 155
序列中,如果要用 300 来做不上升子序列的结尾,那这个子序列的长度最长就是2,然后现在207在这个序列的第二个位置,所以我们应该换成更优的 300 来充当整个序列的不上升子序列长度为2 的末尾数,只有这样,才能保证最优(想一想为什么?只有当前末尾数更大,才更有可能在后面的更新中使得序列更长)。那么怎么找这个位置呢?二分。通过二分,就可以把这个算法复杂度降到nlogn。
到此,第一问的解法已经解释完毕了。
第二问:
求一个序列里面最少有多少不上升子序列等于求这个序列里最长上升子序列的长度。这句话先入为主,然后就可以利用第一问的方法反着求就可以了。
但是我们静下心来仔细想一想,我们如果用O(n^2)做,该怎么做?
可以用一个数组d,d[i]
表示第 i 个拦截系统当前的能打的最大高度。然后用一个变量 num
记录当前的拦截系统的个数。每次遇到a[i]
,从左到右遍历d,找到最小的j
使得d[j]>=a[i]
然后更新d[j] = a[i]
。也就是找到一个高度最合适的拦截系统去拦截导弹。由于d数组是升序的,所以更新之后依然升序。如果不存在这样的j
,那么意味着就要添加导弹d[++j] = a[i]
。
咦!看到这里,你有没有觉得跟上一个问题特别相似。我们可以先检查d[num]>=a[i]
是否成立,如果不成立,则需要增加拦截系统d[++num] = a[i]
。如果成立,那么就需要二分找到最合适的位置去更新。
那么这个求法,是不是就是在求最长上升子序列呢?
int a[100000];
int d[100000];
int n=0;
int l,r,mid;
int main()
{
while(cin>>a[n++]);
int j = 0;
d[0] = a[0];
n--;
for(int i=1;i<n;i++)
{
if(d[j]>=a[i])
d[++j] = a[i];
else
{
l = 0;r=j;
while(l<r)
{
mid = (l+r)>>1;
if(d[mid]>=a[i]) l = mid+1;
else r = mid;
}
d[l] = a[i];
}
}
d[0] = a[0];
int num = 0;
for(int i=1;i<n;i++)
{
if(d[num]<a[i])
{
d[++num] = a[i];continue;
}
l = 0;r = num;
while(l<r)
{
mid = (l+r)>>1;//cout<<mid<<endl;
if(d[mid]>=a[i]) r = mid;
else l = mid+1;
}
d[r] = a[i];
}
cout<<j+1<<endl<<num+1<<endl;
return 0;
}
Luogu-P1020(导弹拦截)(DP,LIS ,二分优化)的更多相关文章
- luogu P1020 导弹拦截 x
首先上题目~ luogu P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都 ...
- P1020 导弹拦截(LIS)
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- 洛谷 P1020 导弹拦截(dp+最长上升子序列变形)
传送门:Problem 1020 https://www.cnblogs.com/violet-acmer/p/9852294.html 讲解此题前,先谈谈何为最长上升子序列,以及求法: 一.相关概念 ...
- P1020 导弹拦截 dp 树状数组维护最长升序列
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- P1020 导弹拦截 /// DP Dilworth定理 LIS、LDS优化
题目大意: https://www.luogu.org/problemnew/show/P1020 Dliworth有两个互相对偶的定理:U的链划分使用的最少集合数,等于它的最大反链长度.(1)U的反 ...
- 【LIS】Luogu P1020 导弹拦截
昨天晚上看蓝书,看到了LIS问题的优化解法. 是比O(n方)更快的解法,实际上是一个常数优化. 先讲一下朴素的解法: 一个集合a,a[i]是第i个元素.设dp[i]为以编号为i的元素结尾的最长不上升子 ...
- 洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理
题目链接:https://www.luogu.com.cn/problem/P1020 题目大意: 给你一串数,求: 这串数的最长不上升子序列的长度: 最少划分成多少个子序列是的这些子序列都是不上升子 ...
- Luogu P1020 导弹拦截
传送门 这道题信息量好大啊 1.Dilworth定理 Dilworth定理:对于一个偏序集,最少链划分等于最长反链长度. Dilworth定理的对偶定理:对于一个偏序集,其最少反链划分数等于其最长链的 ...
- 洛谷 P1020 导弹拦截 (LIS)
第一问最长 不上升子序列,第二问最长上升子序列 套模板就好https://blog.csdn.net/qq_34416123/article/details/81358447 那个神奇的定理当作结论吧 ...
- Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)
Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列) Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺 ...
随机推荐
- bzoj 2440: [中山市选2011]完全平方数【莫比乌斯函数+二分】
二分答案,然后用莫比乌斯函数作为容斥系数,计算当前枚举的mid内有几个满足要求的数 #include<iostream> #include<cstdio> #include&l ...
- bzoj 1076: [SCOI2008]奖励关【状压dp+概率dp】
设f[i][s]为前i步,选的礼物集合为s的方案数,然而并不会转移-- 看了hzwer的blog,发现要倒着转移,然后答案就是f[1][0] 妙啊 #include<iostream> # ...
- Codeforces732F Tourist Reform
求出无向图的所有边双联通分量,然后缩点就成了一颗树. 然后我们选取最大的那个边双联通分量作为根,这样我们就可以确定所有割边的方向了. 对于边双联通分量里面的边,我们随便dfs一下就可以把它变成强连通分 ...
- Oracle 正则化
摘抄自:http://www.cnblogs.com/scottckt/archive/2012/10/11/2719562.html ORACLE中的支持正则表达式的函数主要有下面四个: 1,REG ...
- Github配置SSH连接
安装git.exe,打开Git Bash 1.检查是否已经有SSH Key. $cd /.ssh 2.生成一个新的SSH. $ ssh-keygen -t rsa -C "email@git ...
- Android 暗码表
转自: http://blog.csdn.net/jiangshide/article/details/8192834 不同手机厂商可能会隐藏或修改暗码,部份暗码要谨慎使用,因为可能令手机失去原有的功 ...
- 用eclipse-inst-win64.exe安装eclipse出现Java for Windows Missing 的原因
Java for Windows Missing 因为jdk的版本没有对,我这里是64位的机器上安了32位的jdk,所以一直报这个. 必须换上相对应版本的jdk,提示页面有链接,直接点击就可以下载. ...
- popoverController使用注意--转
一.设置尺寸 提示:不建议,像下面这样吧popover的宽度和高度写死. 1 //1.新建一个内容控制器 2 YYMenuViewController *menuVc=[[YYMenuViewCont ...
- scau 1144 数星星 bit + 扫描线的思想
这题如果用二维树状数组,则会直接爆内存. 那么可以运用扫描线的思路. 就是,它同时被x和y限制了,那么可以在查询的时候,确保x先满足了,(把x按小到大排序) 然后就相当于是关于y的一个一维bit了, ...
- js数据类型之判断
js有几种类型,具体是:字符串(String).数字(Number).布尔(Boolean).数组(Array).对象(Object).空(Null).未定义(Undefined). js提供了typ ...