导弹拦截
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
一行,若干个整数,中间由空格隔开。
输出格式
两行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
样例输入
389 207 155 300 299 170 158 65
样例输出
6
2
提示
对于全部数据,满足导弹的高度为正整数,且不超过 \(5\times 10^4\)。
第一问很简单,因为不能高于前一发的高度,所以就是求最长不上升子序列
第二问需要分析一下
对于任意一个高度,我们当然是希望用以前的系统来拦截,并且要尽可能的矮,如果根本没有,那就只好再添加一个系统了
也就是说只要前面所有系统最后一个导弹的高度都小于这颗导弹,就要再增加一个系统
这个过程不就是典型的最长上升子序列吗
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
int n,ans,cnt,t=1;
const int N=100005;
int a[N],f[N],q[N];
int main()
{
while(~scanf("%d",&a[++n]));n--;
q[t]=a[1];f[1]=1;
for(int i=2;i<=n;i++){//优化版LIS
int x=upper_bound(q+1,q+t,a[i],greater<int>())-q;f[i]=1;
if(x==t&&a[i]<=q[t]) t++,x=t;
f[t]=f[t-1]+1;
q[x]=a[i];
}
printf("%d\n",f[t]);
t=1;q[t]=a[1];f[1]=1;
for(int i=2;i<=n;i++){
int x=lower_bound(q+1,q+t,a[i])-q;f[i]=1;
if(x==t&&a[i]>q[t]) t++,x=t;
f[t]=f[t-1]+1;
q[x]=a[i];
}
printf("%d",f[t]);
return 0;
}