zoukankan      html  css  js  c++  java
  • 导弹拦截p1020(LIS问题)

    题目描述(题目链接:https://www.luogu.org/problem/P1020)

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

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

    输入格式

    11行,若干个整数(个数le 100000100000)

    输出格式

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

    输入输出样例

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

    说明/提示

    为了让大家更好地测试n方算法,本题开启spj,n方100分,nlogn200分

    每点两问,按问给分

     注意:upper_bound函数和lower_bound函数可以传递第四个参数导致功能发生改变

    题解:此题数据量过大,用O(n*n)会超时,所以就需要用到另一种方法:二分查找,之前我有说过c++自带查找函数:https://www.cnblogs.com/cstdio1/p/11262358.html

    这道题的思路就是利用查找函数,基本思路是找到最长的降序序列,序列用d[i]来存储,首先将len1=1,d[len1++]=a[1];a数组是数据输入的高度

    如果之后的a[i]小于等于d[len1],直接将a[i]接到d[len1++]的后面,否则就利用upper_bound(加上greater<int>())函数找出d数组中第一个小于a[i]的数,用a[i]替换掉

    至于为什么要这麽做我举个例子

    d1数组:389 207 155

    如果此时a[i]等于300,d1数组应不应该更新,首先d1数组是要找到最长的降序子序列,那么d1的左侧应该尽量的大(左侧插入元素的空间就很大),d1的右侧应该尽量的小(右边插入的元素也会增多)这样才能够保证找到最长的

    综合上述,此时d1中的207应该更换成300,也就是我上面说的找到第一个小于a[i]的元素,用a[i]替换掉

    同理对于用几个系统就是找最长升序的

    c++代码如下:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=100010;
    int a[N],d1[N],d2[N],n;
    int main() {
        while(cin>>a[++n]);n--;     //输入
        int len1=1,len2=1;      //初始长度为1
        d1[1]=a[1];     //用于求不上升序列长度
        d2[1]=a[1];     //用于求上升序列长度
        for(int i=2; i<=n; i++) {       //从a[2]开始枚举每个数(a[1]已经加进去了)
            if(d1[len1]>=a[i])d1[++len1]=a[i];      //如果满足要求(不上升)就加入d1
            else {      //否则用a[i]替换d1中的一个数
                int p1=upper_bound(d1+1,d1+1+len1,a[i],greater<int>())-d1;
                d1[p1]=a[i]; 
            }
            if(d2[len2]<=a[i])d2[++len2]=a[i];       //同上
            else {
                int p2=lower_bound(d2+1,d2+1+len2,a[i])-d2;
                d2[p2]=a[i];
            }
        }
    
        cout<<len1<<endl<<len2;     //输出
        return 0;     //结束
    }
    不一样的烟火
  • 相关阅读:
    Junit单元测试
    win7的6个网络命令
    WOJ1024 (POJ1985+POJ2631) Exploration 树/BFS
    WOJ1022 Competition of Programming 贪心 WOJ1023 Division dp
    woj1019 Curriculum Schedule 输入输出 woj1020 Adjacent Difference 排序
    woj1018(HDU4384)KING KONG 循环群
    woj1016 cherry blossom woj1017 Billiard ball 几何
    woj1013 Barcelet 字符串 woj1014 Doraemon's Flashlight 几何
    woj1012 Thingk and Count DP好题
    woj1010 alternate sum 数学 woj1011 Finding Teamates 数学
  • 原文地址:https://www.cnblogs.com/cstdio1/p/11329076.html
Copyright © 2011-2022 走看看