题目
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是\le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
1行,若干个整数(个数\le 100000≤100000)
NOIP 原题数据规模不超过 2000。
输出格式
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入样例
389 207 155 300 299 170 158 65
输出样例
6 2
设计思路
这题需求一个不上升序列长度和一个上升序列长度,主要是用lower_bound与upper_bound来进行查找,先创建初始长度为1的len1和len2,d1[1]和d2[1],如上面例子,先将389加入到一个数组中,再比较389和下一个数字207,显然207较小,并加入到数组中,继续往后直到数字300时,不能直接加入到数组,须置换数组中第一个小于300的数字,即207。进行多次加入和替换,就查找出了最多能拦截的导弹数和最少要配备的系统。
下面说明以下lower_bound与upper_bound的用法:
这两个函数都只能用于升序序列,如下例子:
int main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
cout << (lower_bound(a, a + 12, 4) - a) << endl; //输出3
cout << (upper_bound(a, a + 12, 4) - a) << endl; //输出4
}
若序列是降序:
int a[] = {4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1};
cout << (lower_bound(a, a + 12, 4) - a) << endl; //输出12
cout << (upper_bound(a, a + 12, 4) - a) << endl; //输出12
cout << (lower_bound(a, a + 12, 1) - a) << endl; // 输出0
cout << (upper_bound(a, a + 12, 1) - a) << endl; // 输出0
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int a[N], d1[N], d2[N], n;
int main() {
while (cin >> a[++n]); n--;
int len1 = 1, len2 = 1; //初始长度为1
d1[1] = a[1]; //用于求不上升序列长度
d2[1] = a[1]; //用于求上升序列长度
for (int i=2; i<=n; i++) { //从a[2]开始枚举每个数
if (d1[len1] >= a[i]) d1[++len1] = a[i]; //如果满足要求不上升就加入d1
else { //否则用a[i]替换d1中的一个数
int p1 = upper_bound(d1 + 1, d1 + 1 + len1, a[i], greater<int>()) - d1;
d1[p1] = a[i];
}
if (d2[len2] < a[i]) d2[++len2] = a[i];
else {
int p2 = lower_bound(d2 + 1, d2 + 1 + len2, a[i]) - d2;
d2[p2] = a[i];
}
}
cout << len1 << endl << len2;
return 0;
}
运行结果:

大数据201 tyx

该博客讨论了一种导弹拦截系统的设计问题,系统限制了后续炮弹的高度不能超过前一发。文章通过输入导弹飞行高度,计算了系统最多能拦截的导弹数量以及拦截所有导弹所需的最少系统数量。主要利用了lower_bound和upper_bound在排序序列中的应用,实现了不上升序列和上升序列的优化查找。代码示例展示了如何实现这一算法,输出了拦截导弹的最大数量和所需系统数量。
623

被折叠的 条评论
为什么被折叠?



