P1020 导弹拦截

题目描述

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

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

输入输出格式

输入格式:

一行,若干个整数(个数少于100000)

输出格式:

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

输入输出样例

输入样例#1:  复制
389 207 155 300 299 170 158 65
输出样例#1:  复制
6

2




这道题目我用了lower_bound(一个stl里面带的函数),作用是找到一个序列中大于等于查询值的数,并返回这个数的地址。

这题目其实有两问,其中第一问,可以通过构筑一个递减序列,通过lower_bound(内部源代码是利用了二分,效率logN)不断维护这个序列的最优性。而第二问,需要用到一个dilworth定理(水平有限,无法在此证明,同学可以自行百度),意思是求一个序列里面最少有多少最长不上升序列等于求这个序列里最长上升序列的长度,如此转换,第二问就是第一问的反一下,为了能使其应用low_bound函数,我将他们都乘了一个-1

代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100010;
int n=1;
int a[MAXN],b[MAXN],c[MAXN];
int main()
{
while(cin>>a[n])
n++;
int len1=0;
for(int i=1;i<n;i++)
{
if(a[i]>b[len1])
{
len1++;
b[len1]=a[i];
}
else
*lower_bound(b+1,b+len1+1,a[i])=a[i];
}
for(int i=1;i<n;i++)
a[i]*=-1;
int len2=0;
c[len2]=-99999;
for(int i=1;i<n;i++)
{
if(a[i]>=c[len2])
{
len2++;
c[len2]=a[i];
}
else
*upper_bound(c+1,c+len2+1,a[i])=a[i];
}
cout<<len2<<endl<<len1;
return 0;
}

猜你喜欢

转载自blog.csdn.net/ant_e_zz/article/details/80199455