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;
}

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

时间: 2024-10-06 10:43:25

P1020 导弹拦截的相关文章

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

P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个正

p1020导弹拦截

传送门 P1020导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若

【题解】P1020 导弹拦截

[题解]P1020 导弹拦截 从n^2到nlogn 第二问就是贪心 第一问: 简化题意:求最长不下降子序列 普通n^2: for (int i = 1; i <= n; i++) for (int j = 1; j < i; j++) if(a[j] >= a[i]) f[i] = max(f[i], f[j] + 1); cout << f[n]; 另一种n^2级,可能快一点点(还没交,不知对不对) f[0] = 1; for (int i = 1; i <= n;

洛谷 P1020 导弹拦截 【最长上升子序列】 || 【线段树】

题目链接:https://www.luogu.org/problemnew/show/P1020 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹

[ luogu ] P1020 导弹拦截

题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个正整数最多100个. 输

P1020 导弹拦截 Dilworth

题目: 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个整数(个数少于1

P1020 导弹拦截 - 序列DP

传送门 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮 弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个整数(个数少于

P1020 导弹拦截 O(nlogn)做法

题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是 \(\le 50000\)的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入格式 1行,若干个整数(个数 \(\le 10

洛谷P1020导弹拦截——LIS

题目:https://www.luogu.org/problemnew/show/P1020 主要是第二问,使用了dilworth定理:一个序列中最长不上升子序列的最大覆盖=最长上升子序列长度. dilworth定理:http://www.cnblogs.com/nanke/archive/2011/08/11/2134355.html 代码如下: #include<iostream> #include<cstdio> using namespace std; int d,b[10