1012 [NOIP1999]拦截导弹 二分优化 单调上升子序列 单调不降子序列

链接:https://ac.nowcoder.com/acm/contest/24213/1012
来源:牛客网

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入描述:

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

输出描述:

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

输入

复制
389 207 155 300 299 170 158 65

输出

复制
6
2

 

分析

用单调不降子序列求最多拦截的敌机

用单调上升子序列求最少需要的导弹数

单调不降子序列:upper_bound 每次找到大于当前值的位置

单调上升子序列:lower_bound 每次找到大于等于当前值的位置

 

#include<bits/stdc++.h>
#define fo(i,j,n) for(int i = j;i<=n;i++)
#define of(i,n,j) for(int i = n;i>=j;i--)
#define dbb(i,a,b) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<#b<<':'<<b<<endl;
using namespace std;
const int N = 1e5+10,inf = 3e5+10;
int n;
int f[N],flag[N],a[N],cnt,g[N],res;

void solve() {

fill(f,f+n,inf);
fo(i,0,n-1) {
int idx = lower_bound(f,f+n,a[i]) - f;
f[idx] = a[i];
}
int ans2;
of(i,n-1,0) {
if(f[i] != inf) {ans2 = i + 1;break;}
}
// fo(i,0,n-1) cout<<f[i]<<' ' ;
// cout<<endl;
fill(f,f+n,inf);
reverse(a,a+n);
fo(i,0,n-1) {
int idx = upper_bound(f,f+n, a[i]) - f;
f[idx] = a[i];
}

int ans1;
of(i,n-1,0) {
if(f[i] != inf) {
ans1 = i + 1;break;
}
}
cout<<ans1<<endl<<ans2<<endl;
}

int main() {
n = 0;
while(cin>>a[n])n ++;
solve();
}

posted @ 2022-07-06 15:15  er007  阅读(51)  评论(0)    收藏  举报