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;
    }
    
  • 相关阅读:
    level trigger 与 edge trigger 的区别
    使用ifstream时碰到的一个小问题
    转一篇 sed one line
    select(poll)效率,与异步网络IO,AIO, libevent, epoll
    类的成员函数指针的使用
    awk 的OFS使用 小 tips
    一句话打通所有机器,小脚本
    usleep sleep函数会重置clock 的返回值
    qstore 的 chunk重构小记
    判断质数的方法
  • 原文地址:https://www.cnblogs.com/zcxy/p/12994888.html
Copyright © 2011-2022 走看看