首先上题目~

luogu P1020 导弹拦截

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出格式

输入格式:

一行,若干个正整数最多100个。

输出格式:

2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入样例#1:

389 207 155 300 299 170 158 65
输出样例#1:

6
2

思路:From 题解大大!~~~

首先分析题意,第一个问题就是最长不升子序列(好多题解都说反了→_→)

第二个问题,等价于求最长上升子序列

给一个严密的数学证明【证明部分引自CSDN】

这里我们要介绍一个很优美的定理~(优美?)

Dilworth定理:

    对于一个偏序集,最少链划分等于最长反链长度。

Dilworth定理的对偶定理:

    对于一个偏序集,其最少反链划分数等于其最长链的长度。

也就是说把一个数列划分成最少的不升子序列的数目就等于这个数列的最长上升子序列的长度。

下面来说说这个定理是怎么来的:

偏序集的定义:偏序是在集合X上的二元关系≤(这只是个抽象符号,不是“小于或等于”,它满足自反性、反对称性和传递性)。即,对于X中的任意元素a,b和c,有:

  (1)自反性:a≤a;

  (2)反对称性:如果a≤b且b≤a,则有a=b;

  (3)传递性:如果a≤b且b≤c,则a≤c 。

带有偏序关系的集合称为偏序集。

首先令(X,≤)是一个偏序集,对于集合中的两个元素a、b,如果有a≤b或者b≤a,则称a和b是可比的,否则a和b不可比。

在这个例子(反链)中元素Ri<=Rj是指(i<=j) and (ai>=aj)

一个反链A是X的一个子集,它的任意两个元素都不能进行比较。

一个链C是X的一个子集,它的任意两个元素都可比。

【定理】

在X中,对于元素a,如果任意元素b,都有a≤b,则称a为极小元。

定理1:令(X,≤)是一个有限偏序集,并令r是其最大链的大小。则X可以被划分成r个但不能再少的反链。

其对偶定理称为Dilworth定理:

令(X,≤)是一个有限偏序集,并令m是反链的最大的大小。则X可以被划分成m个但不能再少的链。

虽然这两个定理内容相似,但第一个定理证明要简单一些。此处就只证明定理1。

证明:设p为最少反链个数

(1)先证明X不能划分成小于r个反链。由于r是最大链C的大小,C中任两个元素都可比,因此C中任两个元素都不能属于同一反链。所以p>=r。

(2)设X1=X,A1是X1中的极小元的集合。从X1中删除A1得到X2。注意到对于X2中任意元素a2,必存在X1中的元素a1,使得a1<=a2。令A2是X2中极小元的集合,从X2中删除A2得到X3……,最终会有一个Xk非空而Xk+1为空。于是A1,A2,…,Ak就是X的反链的划分,同时存在链a1<=a2<=…<=ak,其中ai在Ai内。由于r是最长链大小,因此r>=k。由于X被划分成了k个反链,因此r>=k>=p。

(3)因此r=p,定理1得证。

【解决】

要求最少的覆盖,按照Dilworth定理

最少链划分 = 最长反链长度

所以最少系统 = 最长导弹高度上升序列长度。

【引用部分结束】

dalao原话是酱紫哒~

然后。。。由于不知道数据范围。。。我抱着书啃了好久,写了个O(nlogn)的算法。。。事后才知道貌似n不大于15以及这个算法超出了NOIP的范围。。。

不过,还是给大家介绍一下吧(以最长上升子序列为例)

由常识(额...什么常识????)可得,在同一个范围内,有两个长度相等的子序列,那么末尾元素较小的那一个,在连接后面的元素时更有优势,因此,如果我们只保留末尾元素最小的那个状态,不会丢掉最优解;

这样我们可以令状态d(i)=长度为i+1的子序列末尾最小元素(如果不存在长度为i+1的上升子序列则为INF)

然后根据上面的推理,我们很容易得到,除掉后面那一串INF外,d是单调递增的

需要注意的是,我们所计算的d是在动态改变的(这也就是我前面强调同一个范围内的原因)

也就是说,我们依次考虑前i个数,随着i的不断增大,d也是在不断改变的

明显,边界条件dp[0]=0;

那么,我们从前到后考虑原数列中的每一个元素a[j]。如果有dp(i-1)<a[j],那么就意味着,a[j]可以加在这个长度为i的这个数列的最后;那么所有满足条件的a[j]中最小的一个,就是dp[i]的值(长度为i+1的上升子序列中的最小末尾元素)

如果这么朴素的实现,也可以在O(n^2)的时间内完成

我们把这个思路转一下,由于d是递增的,所以对于任何一个a[j],它只会有一次被放入dp数组中(以后放入的,一定比它大)

那么应该放在哪里呢?

我们只需要在dp数组中,找到满足dp(k)>=a[j]的第一个下标k,更新d(k)=a[j]即可

为什么这样做是正确的呢?

首先,如果a[j]能够合法地替换掉那个长度为k+1的子序列的末尾元素,也就是a[j]>d[k-1]的话,那么这样做的正确性是很明显的;

如果a[j]<=d[k-1]呢,那么就与k为第一个满足d(k)>=a[j]的下标这一先决条件不符

那么,我们就可以使用二分查找来进行优化,最后输出满足d(i)<INF的最大i值所对应的子序列长(也就是i+1)即可

第一个是自己写一个二分查找,第二个就是

阅读建议:先看后半段求最长上升子序列的,然后再看前半段求不升子序列的,便于理解

代码酱来也~

#include <iostream>
#include <cstdio>
#include <algorithm> using namespace std; const int M = 5e5 +;
int cv[M];
int dp[M]; int main()
{
int tails,lefts,rights;
int i=,j=;
int QwQ;
while(scanf("%d",&QwQ)!=EOF)
{
///原来EOF输入需要Ctrl+Z!QwQ
///我说为什么不出数QwQ
i++;
cv[i]=QwQ;
}
/*
for(j=1;j<=i;j++)
printf("%d ",cv[j]);
*/
///i--;///因为最后的时候输入了一个EOF,需要将其删去,所以i--
dp[]=cv[];///dp
tails=;///设置队尾(队列)
for(j=;j<=i;j++)
{///最长不下降序列
lefts=;
rights=tails;
while(lefts<=rights)///二分?
{
int mids=(lefts+rights)/;
if(dp[mids] >= cv[j])
lefts=mids+;
else rights=mids-;
}
dp[lefts]=cv[j];///进行修改
if(lefts > tails) tails++;///入队
}
printf("%d\n",tails);///换行符!!!血的教训啊!!!
for(j=;j<=i;j++)///清空!
dp[j]=; ///又来一遍hhhh
tails=;
dp[]=cv[];
for(j=;j<=i;j++)
{///最长上升序列
lefts=;
rights=tails;
while(lefts<=rights)///二分w
{
int mids=(rights+lefts)/;
if(dp[mids] < cv[j])
lefts=mids+;///这一次求的是最长上升序列w
else rights=mids-;
}
dp[lefts]=cv[j];///进行修改
if(lefts > tails) tails++;///入队
}
printf("%d\n",tails); return ;
}

二分查找

#include<iostream>

using namespace std;

int h[],ht[],f[];
int ans=,l=; int main()
{
while(cin>>h[l])
l++;
f[]=0x7fffffff;
for(int i=; i<l; i++)
for(int j=ans; j>=; j--)
if(f[j]>=h[i])
{
f[j+]=h[i];
ans=max(ans,j+);
break;
}
cout<<ans;
ans=;
for(int i=; i<l; i++)
{
for(int j=; j<=ans; j++)
{
if(ht[j]>=h[i])
{
ht[j]=h[i];
break;
}
}
if(ht[ans]<h[i]) ht[++ans]=h[i];
}
cout<<endl<<ans;
return ;
}

DP

End.

luogu P1020 导弹拦截 x的更多相关文章

  1. 【LIS】Luogu P1020 导弹拦截

    昨天晚上看蓝书,看到了LIS问题的优化解法. 是比O(n方)更快的解法,实际上是一个常数优化. 先讲一下朴素的解法: 一个集合a,a[i]是第i个元素.设dp[i]为以编号为i的元素结尾的最长不上升子 ...

  2. Luogu P1020 导弹拦截

    传送门 这道题信息量好大啊 1.Dilworth定理 Dilworth定理:对于一个偏序集,最少链划分等于最长反链长度. Dilworth定理的对偶定理:对于一个偏序集,其最少反链划分数等于其最长链的 ...

  3. Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)

    Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列) Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺 ...

  4. codevs1044 拦截导弹==洛谷 P1020 导弹拦截

    P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天 ...

  5. p1020导弹拦截

    传送门 P1020导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度 ...

  6. 【题解】P1020 导弹拦截

    [题解]P1020 导弹拦截 从n^2到nlogn 第二问就是贪心,不多说 第一问: 简化题意:求最长不下降子序列 普通n^2: for (int i = 1; i <= n; i++) for ...

  7. 洛谷 P1020导弹拦截题解

    洛谷链接:https://www.luogu.org/problem/P1020 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到 ...

  8. codevs——T1044 拦截导弹 || 洛谷——P1020 导弹拦截

    http://codevs.cn/problem/1044/ || https://www.luogu.org/problem/show?pid=1020#sub 时间限制: 1 s  空间限制: 1 ...

  9. P1020 导弹拦截(LIS)

    题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...

随机推荐

  1. Powershell指令集_2

    目录 目录 获取证书 Get-Childitem 调用REST API Invoke-RestMethod 选择对象属性 Select-Object 导入模块 Invoke-Expression 路径 ...

  2. sklearn版本

    10.19.0以前的sklearn版本才有cross_validation包,这个时候不要用model_selection导入StratifiedKFold,要用cross_validation,0. ...

  3. UDP 首部的格式

    <图解TCP/IP>6.6 UDP首部的格式 源端口号:表示发送端端口号,字段长16位.该字段是可选项,有时可能不会设置源端口号.没有源端口号的时候该字段的设置为0.可用于不需要返回的通信 ...

  4. 小白学数据分析--留存率分析_I次日留存率突然下降了50%

    小白学数据分析--留存率分析_I次日留存率突然下降了50% 最近在做留存分析时,遇到了不少的情况,也经常会有人问我,为什么我的游戏突然次日留存率降了一半.如果留存率是单单作为一个简单的指标的话,那对你 ...

  5. Appium-入门实例1

    参考:(https://blog.csdn.net/zh175578809/article/details/76862590) 第一步:启动虚拟设备 在运行App之前,首先需要创建一个Android模 ...

  6. arduino库函数1

    https://wenku.baidu.com/view/e657b1f0bcd126fff6050baf.html 的阅读笔记.现在到了 第四十页. setup应该是 在开始 执行一次. 然后 lo ...

  7. idea注册

    1:要先得到一个注册码 http://idea.lanyus.com/ 2:之后需要在引导下 修改文件 使用前请将“0.0.0.0 account.jetbrains.com”添加到hosts文件中

  8. .Net core 3.0 SignalR+Vue 实现简单的即时通讯/聊天IM (无jq依赖)

    .Net core 中的SignalR JavaScript客户端已经不需要依赖Jquery了 一.服务端 1.nuget安装 Microsoft.AspNetCore.SignalR 2.在star ...

  9. Trie字典树详解

    今天上午省选字符串......只会KMP.连hash都不会的我被大佬虐惨了......于是我要发奋图强学习字符串,学习字符串当然就要从Trie树这种可爱的数据结构开始啦!!! 一.什么是Trie树?? ...

  10. SCUT - 153 - 小马哥和他的山脉 - 线段树

    https://scut.online/p/153 其实不需要用线段树,只关心相邻元素的差,像神仙那样用差分就可以O1维护的. 但是我偏要用. 交之前写的那个,注意没有st本身的线段树只有lazy标记 ...