1012 [NOIP1999]拦截导弹 二分优化 单调上升子序列 单调不降子序列
链接:https://ac.nowcoder.com/acm/contest/24213/1012
来源:牛客网
题目描述
输入描述:
1行,若干个整数(个数≤100000)
输出描述:
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();
}