码迷,mamicode.com
首页 > 其他好文 > 详细

P1020 导弹拦截

时间:2018-02-10 12:50:49      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:ring   计算   不能   name   有一个   pre   bit   log   依次   

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

输入导弹依次飞来的高度(雷达给出的高度数据是不大于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 导弹拦截

标签:ring   计算   不能   name   有一个   pre   bit   log   依次   

原文地址:https://www.cnblogs.com/planche/p/8438179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!