洛谷P1020:导弹拦截
P1020 [NOIP1999 普及组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题其实是两个问题的结合,可以互不干扰地求出。
第一个问题,NOPI里是可以用o(n^2)的时间复杂度算出来,但是洛谷提高了要求,得用o(nlogn)的时间复杂度求出来。
那我先介绍时间复杂度为n^2的dp算法。
写dp前先确认每个阶段的含义,这里我们定义每个阶段的含义为:以第i个数字为结尾的最长非增子串。
我们把每个阶段的决策抽象为一个点,那么我们先确认一下每个点的决策依据,即父节点。
我们可以很容易地想出我们可以遍历第i个点前面的点j,并在满足条件
下找到最大值。
那么接下来就是代码了。
#include<iostream>
#include<algorithm>
using namespace std;const int N=100010;int st[N];//存储每个数
int dp[N];//dp[i]为以i为结尾的最长子串的长度
int ans;
int n;int main(){cin>>n; for(int i=1;i<=n;i++) scanf("%d",&st[i]);for(int i=1;i<=n;i++){//遍历每个阶段if(i==1) dp[i]=1;int a=0;for(int j=i-1;j>0;j--){//找到最优决策if(st[i]<=st[j])a=max(a,dp[j]);}dp[i]=a+1;ans=max(ans,dp[i]);}cout<<ans;
}
那么接下来就是nlogn的算法了。
这个时候我们每个dp的含义就变了,dp[i]为长度为i时最大高度,并且用一个数len来记录当前最大的长度。
那么我们就确认每个阶段的父节点是什么,从dp数组的实际含义出发,我们只需要遍历每个点,然后利用该点的数值更新dp数组,即当数值小于dp[len]时我们让dp[len+1]=st[i],并且让len++,如果否的话,我们就寻找长度最小的,且结尾数小于st[i]的,并将其更新为st[i],这里因为dp数组是严格非增的,所以我们可以用二分来寻找这个数。
下面是具体代码;
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;const int N=100010;int dp[N],len=0;
int st[N];
int n;int main(){while(scanf("%d",&st[n])!=EOF) n++;memset(dp,0x3f3f3f3f,sizeof dp);//先将每个数都初始化到足够大for(int i=0;i<n;i++){//遍历每个数,并依次更新dp数组if(st[i]<=dp[len]) dp[++len]=st[i];//当小于当前最大长度里存储的数时,我们将长度+1,并赋值else{//二分找到对应的下标int l=0,r=len;while(l<r){int mid=l+r+1>>1;if(st[i]<=dp[mid]) l=mid;else r=mid-1;}dp[l+1]=st[i];//l为长度最大且dp[l]>=st[i]的下标,l+1即为长度最小且dp[l+1]<st[i]的下标}}cout<<len<<endl;}
那么接下来就是解决另外一个问题了,即求序列在最少可以排列出多少个非增子序列。
具体的话可以看代码,因为本菜鸟时间紧张,所以就不细说了,可以拿一个案例来模拟一下。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;const int N=100010;int st[N];
int n;
vector<int> p;void get(int x){int rcod=-1;for(int i=0;i<p.size();i++){if(x<=p[i]){if(p[rcod]>=p[i]||rcod==-1)rcod=i;}}if(rcod!=-1) p[rcod]=x;else p.push_back(x);}int main(){while(scanf("%d",&st[n])!=EOF) n++;p.push_back(st[0]);for(int i=1;i<n;i++){get(st[i]);}cout<<p.size();}
洛谷P1020:导弹拦截相关推荐
- 洛谷 [P1020] 导弹拦截 (N*logN)
首先此一眼就能看出来是一个非常基础的最长不下降子序列(LIS),其朴素的 N^2做法很简单,但如何将其优化成为N*logN? 我们不妨换一个思路,维护一个f数组,f[x]表示长度为x的LIS的最大的最 ...
- 洛谷1020导弹拦截
Dilworth定理的证明:http://www.cnblogs.com/nanke/archive/2011/08/11/2134355.html 感觉难理解.有空研究. #include<i ...
- luogu P1020 导弹拦截
P1020 导弹拦截 1.Dilworth定理:对于一个偏序集,最少链划分等于最长反链长度. 其实就是说,对于一个序列, 最大上升子序列长度 = 不上升子序列个数 最大不上升子序列长度 = 上升子序列 ...
- 洛谷P1020/CODEVS1044 导弹拦截(拦截导弹)
本题地址: http://www.luogu.org/problem/show?pid=1020 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的 ...
- 导弹拦截(洛谷-P1020)
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- P1020 导弹拦截(LIS)
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- P1020 导弹拦截(最长不上升序列+二分)
题目链接 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到 ...
- P1020 导弹拦截(n*log n时间的最长上升子序列思想)
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- P1020 导弹拦截
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
最新文章
- db2 replace函数的用法_SQL基础知识:常用字符处理函数
- 构建高性能.NET应用之配置高可用IIS服务器-第四篇 IIS常见问题之:工作进程回收机制(上)
- 进军人工智能,数学基础很重要?
- [2020多校A层12.3]虚构推理(语言/二分/数据结构)
- react不同环境不同配置angular_前端问题集:vue配置环境-给不同的环境配不同的打包命令...
- gitbook使用实录
- cygwin的离线安装包
- 快速查看当前APP包名
- 烽火吉比特HG261GU获取超级密码教程
- 简单有限元分析技术(详细步骤讲解)
- OCR-CTPN 文字检测
- Android逆向第二天
- All in!马斯克出价430亿美元收购Twitter全部股份,还有B计划
- java 纯真地址库_JAVA解析纯真IP地址库
- cygwin apt-cyg
- 如何用 Telemetry 测试移动 APP H5性能?
- Windows10操作系统共享文件夹给VMWare虚拟机centos 7 操作系统使用
- vi 撤销上一步操作
- 国产系统独创!Linux环境完美兼容原生安卓App
- mycat原理及分表分库入门