题目描述:某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
输入:输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
输出:对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统
示例输入:8 389 207 155 300 299 170 158 65
示例输出:2
在最长上升子序列的算法中,有一个low数组,这个数组含义是low[i]表示长度为i的上升子序列的最后一个数字是多少,当然low[i]要越小越好,low的数组满足low[i+1]>low[i],所以才会有个二分的操作。
在这道题里面:每个导弹系统是个不上升子序列,保证要系统个数最小,那可以考虑当前已经有n个导弹系统了,再来一个导弹,那当然会在这n个导弹系统里面选一个,从左到右找找知道找到一个导弹系统能够击落这个导弹,那维持这样的操作,这n个导弹系统就满足了递增的性质,而再看看这个找的操作,不就是low数组找的操作吗(把low数组理解成导弹系统即可),而如果又有一发特别高的导弹,那增加一个导弹系统不就是最长上升子序列增加个长度么。。所以就找最长上升子序列就完事儿了
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=3e4;
const int INF=0x3f3f3f3f;
int low[maxn+100];
int value[maxn+100];
int main()
{
int n,ans;
while(scanf("%d",&n)!=EOF)
{
ans=0;low[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&value[i]);
low[i]=INF;
}
for(int i=1;i<=n;i++)
{
if(value[i]>low[ans])
low[++ans]=value[i];
else
{
int l=1,r=ans;
while(l<=r)
{
int mid=(l+r)/2;
if(low[mid]<value[i]) l=mid+1;
else r=mid-1;
}
low[l]=value[i];
}
}
printf("%d\n",ans);
}
return 0;
}