zoukankan      html  css  js  c++  java
  • P1020 导弹拦截

    题目描述

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

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

    输入格式

    1行,若干个整数(个数≤100000)

    输出格式

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

    思路:

    第一问就是求最长不上升子序列,由于数据是100000,用 n2 的普通DP不行,用贪心二分优化的 nlogn 算法。
    第二问也是一个贪心,用q[i]表示用到的第i个系统的最后一个元素,对每一个输入的元素进行判断,如果当前存在的系统满足加入这个值的条件,那么就用现有的,否则重新开一个系统。
    如果有多个满足条件的系统,那么选择哪一个呢,很明显是选择第一个大于等于这个的值的系统。

    如何证明q数组是有序的 : 对于每个新加的系统,必有之前的所有系统的最后一个值小于当前要加入的值,所以q数组是正序的。

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 100010;
    
    int n;
    int a[N],f[N],q[N];
    
    int main()
    {
        int n = 1;
        while(cin >> a[n]) n++;
        n--;
        
        int len = 0;
        for(int i = 1;i <= n;i++)
        {
            int l = 0,r = len;
            while(l < r)       // 找到最后一个大于等于 a[i] 的数,用大数来更新后面的小数
            {
                int mid = l+r+1 >> 1;
                if(f[mid] >= a[i]) l = mid;
                else r = mid - 1;
            }
            len = max(r+1, len);
            f[r+1] = a[i];
        }
        cout << len << endl;
        
        int cnt = 0;
        for(int i = 1;i <= n;i++)
        {
            int k = 1;
            while(q[k] < a[i] && k <= cnt) k++;   // 找到第一个大于等于a[i]的系统
            q[k] = a[i];
            if(k > cnt) cnt++;
        }
        cout << cnt << endl;
        
        return 0;
    }
    
  • 相关阅读:
    proxySql 报错connection is locked to hostgroup 100 but trying to reach hostgroup 200 解决办法
    构建harbor私有仓库
    Kubernetes Secret
    Kubernetes conifgMap
    kubernetes Ingress详解
    Kubernetes Service 详解
    RC、RS与Deployment的创建
    Pod的生命周期
    kubeadm安装Kubernetes单节点master集群
    App 需要的费用说明
  • 原文地址:https://www.cnblogs.com/zcxy/p/12994888.html
Copyright © 2011-2022 走看看