P1020 [NOIP 1999 提高组] 导弹拦截

题目描述

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

输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式

一行,若干个整数,中间由空格隔开。

输出格式

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

输入输出样例

输入 

389 207 155 300 299 170 158 65

输出 

6
2

代码

无注释版

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int a[N],b[N];
int ans,cnt;
int x,n;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0); 
	while(cin>>x){
		a[++n]=x;
	}
	b[0]=2e9;
	for(int i=1;i<=n;i++){
		if(a[i]<=b[cnt]) b[++cnt]=a[i];
	    else{
	    	int l=1,r=cnt;
	    	while(l<r){
	    		int mid=l+r>>1;
	    		if(b[mid]<a[i]) r=mid;
	    		else l=mid+1;
			}
			b[l]=a[i];
		}
	}
	cout<<cnt<<"\n";
	cnt=0;
	b[0]=-2e9;
	for(int i=1;i<=n;i++){
		if(a[i]>b[cnt]) b[++cnt]=a[i];
		else{
			int l=1,r=cnt;
			while(l<r){
				int mid=l+r>>1;
				if(b[mid]>=a[i]) r=mid;
				else l=mid+1;
			}
			b[l]=a[i]; 
		}
	} 
	cout<<cnt<<"\n";
} 

有注释版

#include<bits/stdc++.h>  // 引入标准库,包含所有常用的C++库
using namespace std;  // 使用标准命名空间

const int N = 100010;  // 定义常量N,表示最大导弹数
int a[N], b[N];  // a数组存储导弹的高度,b数组用于动态规划存储可拦截导弹的最大数目
int ans, cnt;  // ans保存最大拦截导弹数,cnt保存当前拦截的导弹数目
int x, n;  // x为当前导弹高度,n为导弹数量

int main() {
    ios::sync_with_stdio(false);  // 提高输入输出效率
    cin.tie(0);  // 解绑cin和cout,避免不必要的同步
    cout.tie(0);  // 解绑cin和cout

    // 输入所有导弹的高度
    while(cin >> x) {  // 循环读取输入的导弹高度
        a[++n] = x;  // 将每个导弹的高度放入数组a中
    }

    // 计算最大拦截导弹数
    b[0] = 2e9;  // 初始化b[0]为一个很大的数,作为参考值
    for(int i = 1; i <= n; i++) {  // 从第1个导弹到第n个导弹
        if(a[i] <= b[cnt])  // 如果当前导弹的高度小于等于当前已拦截的最大高度
            b[++cnt] = a[i];  // 将当前导弹高度放入b数组,增加已拦截的导弹数
        else {  // 否则,找到一个合适的位置替换
            int l = 1, r = cnt;  // 定义二分查找的范围
            while(l < r) {  // 二分查找
                int mid = (l + r) >> 1;  // 计算中点
                if(b[mid] < a[i])  // 如果b[mid]小于当前导弹高度
                    r = mid;  // 更新r为mid
                else
                    l = mid + 1;  // 否则更新l为mid+1
            }
            b[l] = a[i];  // 将当前导弹的高度放入b数组的正确位置
        }
    }

    // 输出最多能拦截的导弹数量
    cout << cnt << "\n";  // cnt为最大拦截导弹数目

    // 计算最少需要几套系统
    cnt = 0;  // 重新初始化cnt为0
    b[0] = -2e9;  // 初始化b[0]为一个很小的数,作为参考值
    for(int i = 1; i <= n; i++) {  // 从第1个导弹到第n个导弹
        if(a[i] > b[cnt])  // 如果当前导弹的高度大于已拦截导弹的最大高度
            b[++cnt] = a[i];  // 将当前导弹高度放入b数组,增加已拦截的导弹数
        else {  // 否则,找到一个合适的位置替换
            int l = 1, r = cnt;  // 定义二分查找的范围
            while(l < r) {  // 二分查找
                int mid = (l + r) >> 1;  // 计算中点
                if(b[mid] >= a[i])  // 如果b[mid]大于等于当前导弹高度
                    r = mid;  // 更新r为mid
                else
                    l = mid + 1;  // 否则更新l为mid+1
            }
            b[l] = a[i];  // 将当前导弹的高度放入b数组的正确位置
        }
    }

    // 输出最少需要的导弹拦截系统数量
    cout << cnt << "\n";  // cnt为最少需要的拦截系统数量
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值