题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
一行,若干个整数,中间由空格隔开。
输出格式
两行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
输入
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为最少需要的拦截系统数量
}