P1020 导弹拦截
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是 \le 50000≤50000 的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出格式
输入格式:11 行,若干个整数(个数 \le 100000≤100000 )
输出格式:22 行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
说明
为了让大家更好地测试n方算法,本题开启spj,n方100分,nlogn200分
每点两问,按问给分
分析:
学了dp最长不上升子序列,于是找了一道很早以前说要做却没有做的题目来练习。
有两问,第一问我把它反转了一下,然后做最长不上升子序列。
第二问贪心吧。。。不知道我的复杂度是多少,竟然过了。
按理说正规贪心是枚举,然后加二分查找,就是nlogn,
然而,我并没有二分查找,只是判断停下来的位置,不断地扫,直到全部扫完。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int mm=100000;
const int INF=0x3f3f3f3f;
int f[mm+10];
int x;
int q;
int temp[mm+10];
int a[mm+10];
int hashh[mm+10];
int main()
{
while(~scanf("%d",&x))
{
q++;
temp[q]=x;
}
memset(f,0x3f,sizeof(f));
for(int i=1; i<=q; i++)
{
a[q-i]=temp[i];
}
for(int i=0; i<q; i++)
{
*upper_bound(f,f+q,a[i])=a[i];
}
int anss=lower_bound(f,f+q,0x3f3f3f3f)-f;
cout<<anss<<endl;
int cish=0;
int flag=0;
int pos=1;
int maxx=INF;
int ans=0;
while(cish!=q)
{
/*cout<<"================="<<endl;
for(int i=1;i<=q;i++)
cout<<hashh[i]<<" ";
cout<<endl;
cout<<"================="<<endl;
cout<<"pos="<<pos<<endl;
*/
maxx=INF;
ans++;
flag=0;
for(int i=pos; i<=q; i++)
{
if(hashh[i]==1)
continue;
else
{
if(temp[i]<=maxx)
{
cish++;
hashh[i]=1;
maxx=temp[i];
}
else
{
if(flag==0)
{
pos=i;
flag=1;
}
}
}
}
///cout<<"ok"<<endl;
}
cout<<ans;
return 0;
}