P1020题解
Aurora_Lights · · 题解
题意
给定
分析
题目要求两个不同的问题的答案,我们可以分开处理。
- 求最多能拦截多少颗导弹
根据题意可知,由于这套系统后一次的高度不能高于前一次的高度,因此它拦截下来的导弹的高度一定是不上升的。而为了要拦截更多的导弹,我们要使得这个序列尽可能的长。于是问题便转化为求最长不上升子序列。
那么这一问就十分简单了。我们回顾一下如何实现 dp。设
这样的转移时间复杂度为
此部分核心代码见下:
d[1]=a[1];
for(int i=2;i<=n;i++)
{
if(a[i]<=d[len]) d[++len]=a[i];
else d[upper_bound(d+1,d+len+1,a[i],greater<int>())-d]=a[i];
}
时间复杂度
- 求最少需要多少套系统
既然要最少的系统,我们对于每一套系统都要“用干净”,即尽量多次使用,避免浪费。很容易想到用贪心了。每一次从已有的系统里找第一个大于等于当前高度
时间复杂度
for(int i=1;i<=n;i++)//xl 为目前已有系统的数量,x[i] 表示第 i 个系统的高度
{
if(x[xl]<a[i])
{
xl++;
x[xl]=a[i];
}
else
{
int k=lower_bound(x+1,x+xl+1,a[i])-x;
x[k]=a[i];
}
}
cout<<xl;
代码
分析完毕,想必这题已经基本上解决了。这里把完整代码放出来,方便大家调试。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,ma,d[100001],a[100001],k,x[100001],xl=1,t,len=1;
int main()
{
ios::sync_with_stdio(false);
x[1]=0x7fffffff;
while(cin>>a[++n]);
d[1]=a[1];
for(int i=2;i<=n;i++)
{
if(a[i]<=d[len]) d[++len]=a[i];
else d[upper_bound(d+1,d+len+1,a[i],greater<int>())-d]=a[i];
}
cout<<len-1<<endl;
for(int i=1;i<=n;i++)
{
t=0;
if(x[xl]<a[i])
{
xl++;
x[xl]=a[i];
}
else
{
int k=lower_bound(x+1,x+xl+1,a[i])-x;
x[k]=a[i];
}
}
cout<<xl;
return 0;
}