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

Posted 00isok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1020 导弹拦截 最长上升子序列 || 线段树相关的知识,希望对你有一定的参考价值。

题目链接:https://www.luogu.org/problemnew/show/P1020

题目描述

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

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

输入格式:

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

输出格式:

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

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

下面我的代码是WA的,只不过我还不知道为什么WA,先记录下来,至于线段树做法,等以后学会了再来补吧。


#include <bits/stdc++.h>              //此题主要是不知道如何用stl中的upper_bound()函数对结构体中的某一特定元素进行二分
using namespace std;                  //当然,也可也写一个二分子函数对该结构体进行二分,但是还是过不了,此题先记录着吧
int arr[100010];
int vis[100010] = {0};

struct node
{
    int val;
    int loc;
}lis[100010];

struct cmp1
{
    bool operator () (const node &a, const node &b) const {
        return a.val < b.val;
    }
};

int main()
{
    int num = 0;    //记录下标记了多少个导弹
    int a, len = 0,res=0;
    while (cin >> a) {
        arr[++res] = a;      //res为导弹的数量
    }
    int ans = 0; int cas = 0;
    while (num != res) {
        for (int i = 1; i <= res; i++)
        {
            if (!vis[i])
            {
                if (arr[i] > lis[len].val) {
                    lis[++len].val = arr[i];
                    lis[len].loc = i;
                    vis[i] = 1;
                }
                else
                {        //*******对结构体中的某一个元素进行二分查找的方法,详情见上面的cmp()函数
                    node cur; cur.val = arr[i];
                    int j = upper_bound(lis + 1, lis + len + 1, cur,cmp1()) - lis;      //由于这是最长不上升子序列,所以用upper_bound()函数
                    vis[lis[j].loc] = 0;         //由于原来最长上升子序列中的数此时不用了,所以要取消标记
                    lis[j].val = arr[i];
                    lis[j].loc = i;
                    vis[i] = 1;        //标记此时要用的数
                }
            }
        }
        if (!cas)cout << len<<endl;
        num += len;
        len = 0; memset(lis, 0, sizeof(lis));
        ++cas;
        ++ans;         //导弹系统的数量
    }
    cout << ans << endl;
    return 0;
}



2018-05-20

以上是关于洛谷 P1020 导弹拦截 最长上升子序列 || 线段树的主要内容,如果未能解决你的问题,请参考以下文章

线性状态动态规划 P1020 导弹拦截最长上升子序列

导弹拦截 p1020

luogu P1020 导弹拦截

洛谷 [P1020] 导弹拦截 (N*logN)

动态规划 最长上升子序列模型——进阶

动态规划 最长上升子序列模型——进阶