P1020 导弹拦截

Posted planche

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1020 导弹拦截相关的知识,希望对你有一定的参考价值。

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

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

输入输出格式 
输入格式: 
一行,若干个整数(个数少于100000)

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

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


说明 
复杂度: nlogn

Dilworth定理 
在一个序列中 最长下降子序列的个数就等于其最长不下降子序列的长度

所以呢这题就是求最长不上升子序列长度和最长上升子序列长度

upperbound,lowerbound写法

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define inf 0x3f3f3f3f
int dp1[maxn],dp2[maxn];
int n=0,a[maxn];
int len1,len2;
int cmp(int x,int y)
{
    return x>y;
}

int main()
{

    while(scanf("%d",&a[++n])!=EOF);
    n--;//处理EOF的那一次
    fill(dp2,dp2+n+1,inf);
    len1=1;
    len2=1;
    for(int i=1; i<=n; i++)
    {
        int k1=upper_bound(dp1+1,dp1+1+n,a[i],cmp)-dp1;
        int k2=lower_bound(dp2+1,dp2+1+n,a[i])-dp2;
        dp1[k1]=a[i];
        dp2[k2]=a[i];
        len1=max(len1,k1);
        len2=max(len2,k2);
    }
    cout<<len1<<endl<<len2;
    return 0;
}

直接二分写

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
#define maxn 300000+5
const int inf=0x3f3f3f3f;
int a[maxn];
int n=0;
int dp1[maxn],dp2[maxn];
int len1=0,len2=0;

//寻找刚好小于x的下标
int pos1(int l,int r, int x)
{
    if(x<=dp1[len1])
        return len1=len1+1;
    while(l < r)
    {
        int m = l + (r-l)/2;
        if(dp1[m] >= x)  //千万别写成a[m],脑袋要清晰点
            l = m + 1;
        else
            r = m;
    }
    return r;
}
//寻找大于等于x的下标
int pos2(int l,int r,int x)
{
    if(x>dp2[len2])
        return len2=len2+1;
    while(l<r)
    {
        int m=l+((r-l)>>1);
        if(dp2[m]<x)
            l=m+1;
        else
            r=m;
    }
    return r;
}

int main()
{
    while(scanf("%d",&a[++n])!=EOF);
    n--;
    dp1[0]=inf;
    dp2[0]=-inf;
    for(int i=1; i<=n; i++)
    {
        int k1=pos1(1,len1,a[i]);
        int k2=pos2(1,len2,a[i]);
        dp1[k1]=a[i];
        dp2[k2]=a[i];
    }
    cout<<len1<<endl<<len2;

    return 0;
}

 

以上是关于P1020 导弹拦截的主要内容,如果未能解决你的问题,请参考以下文章

P1020 导弹拦截

codevs1044 拦截导弹==洛谷 P1020 导弹拦截

P1020导弹拦截(超详细)(21.10.18)

[ luogu ] P1020 导弹拦截

P1020 导弹拦截

luogu P1020 导弹拦截