拦截导弹

来源:互联网 发布:网红开的淘宝店有哪些 编辑:程序博客网 时间:2024/05/17 23:01

问题描述 Description

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


输入描述 Input Description

第一行为一个整数 N,表示飞来的导弹个数, N100000
第二行为 N 个整数,依次表示导弹飞来的高度,高度数据为不大于 30000 的正整数。


输出描述 Output Description

第一行,输出计算这套系统最多能拦截多少导弹
第二行,输出要拦截所有导弹最少要配备多少套这种导弹拦截系统。


输入样例 Sample Input

8
389 207 155 300 299 170 158 65


输出样例 Sample Output

6
2


分析

第一问是求最长不增子序列。
第二问是求最长递增子序列。可以这么想,设最长递增子序列长度为 s,因为拦截 a1 需要使用一套装置, a2>ai ,所以拦截 a2 不能用拦截 a1 的装置,a3>a2>a1 ,所以拦截 a3 不能用拦截 a2,a1 的装置…所以最少要用 s 套装置,可以利用差不多的思路证明最多要用 s 套装置


代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef bool(*cmper)(int,int);int a[100100];int f[100100];int n;void work(cmper);bool lower(int,int);bool Super(int,int);int binary(int,int,int,cmper);int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i)        scanf("%d",&a[i]);    work(Super);    work(lower);    return 0;}void work(cmper cmp1){    f[f[0]=1] = a[1];    for(int i=2;i<=n;++i){        if(cmp1(f[f[0]],a[i]))            f[++f[0]] = a[i];        else if(!cmp1(f[1],a[i]))            f[1] = a[i];        else            f[binary(1,f[0],a[i],cmp1)] = a[i];    }    printf("%d\n",f[0]);}bool lower(int a,int b){    return a<b;}bool Super(int a,int b){    return a>=b;}int binary(int L,int R,int number,cmper cmp){    int M;    while(L+1 < R){        M = (L+R)>>1;        if(f[M] == number){            while(f[M]==number)                ++M;            return M;        }        else if(cmp(f[M],number))            L = M;        else             R = M;    }    return R;}
0 0
原创粉丝点击