zoukankan      html  css  js  c++  java
  • 洛谷P1020 导弹拦截【单调栈】

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

    题意:

    给定一些导弹的高度。

    一个导弹系统只能拦截高度不增的一系列导弹,问如果只有一个系统最多能拦截多少导弹。

    再问,如果要拦截所有导弹最少需要多少系统。

    思路:

    对于第一个问题其实就是找整个序列中的最长不升子序列。

    对于第二个问题就是找整个序列中的最长上升子序列。因为当有一个高度大于前面的高度时一个系统就搞定不了了。

    最长上升子序列用动态规划是可以做的,但是这题会卡。

    $O(N^2)$的动规做法是,$dp[i] = max(dp[i], dp[j] + 1),if height[i] > height[j]$

    还有一种$O(NlogN)$的做法。这时我们维护一个单调栈。数是从小到大排序的,对于新的一个数,如果比栈顶的元素大,就直接加入栈中。

    如果新的数比栈顶要小,我们就在栈中二分查找一个最小的大于新的数的数替换掉。

    因为对于已经选好了的序列,我们替换前面的数的话并不会影响答案的长度。但是用更小的数替换大的数将有更大的机会让加入的数变多。

    而二分找这样的数也非常简单,使用STL里的upper_bound()和lower_bound()就可以解决了。

    lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。

    upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。

    lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。

    upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x7fffffff
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<string, string> pr;
    17 
    18 const int maxn = 1e5 + 5;
    19 int height[maxn];
    20 int n = 0;
    21 int incre[maxn], decre[maxn];
    22 int len1 = 0, len2 = 0;
    23 
    24 int main()
    25 {
    26     while(scanf("%d", &height[n++]) != EOF);
    27     for(int i = 0; i < n; i++){
    28         if(height[i] > incre[len1]){
    29             incre[++len1] = height[i];
    30         }
    31         else{
    32             int j = lower_bound(incre, incre + len1 + 1, height[i]) - incre;
    33             incre[j] = height[i];
    34         }
    35         
    36         if(height[i] <= decre[len2]){
    37             decre[++len2] = height[i];
    38         }
    39         else{
    40             int j = upper_bound(decre, decre + len2 + 1, height[i], greater<int>() ) - decre;
    41             decre[j] = height[i];
    42         }
    43     }
    44     
    45     
    46     printf("%d
    %d
    ", len2, len1);
    47     return 0; 
    48 }
  • 相关阅读:
    【Java123】JDBC数据库连接池建立
    【招聘123】Some good open positions
    [Java123]Gradle
    4_3:流程控制:循环练习
    4_3:流程控制:while + do while + continue + break
    4_2:流程控制:[ for循环 ] + 断点调试
    4_1:流程控制:分支结构:[ if else ] + [ 三元表达式 ] + [ switch case ]
    3:运算符 + 运算符优先级 [ 逻辑短路 ]
    2_3:变量:[ 类型之间转换 ]
    2_2:变量:[ 五种简单数据类型 ]
  • 原文地址:https://www.cnblogs.com/wyboooo/p/10805027.html
Copyright © 2011-2022 走看看