题目背景
易琢然今天玩使命召唤,被敌军用空对地导弹轰炸,很不爽;众所周知,易琢然很不老实,他开了外挂;
外挂第一次可以打掉任意高度的导弹,之后每一次都不能打掉大于上一次高度的导弹;
但易琢然水平太差,敌军最多有300000颗导弹,导弹只能按顺序打,因为外挂有BUG,而且是超音速导弹,只有一秒导弹就到了,只能编程解决;
但易琢然上课不认真,平时帮他的sxy又不在,所以他只能求助于你
题目描述
有n颗导弹(n<=300000),求易琢然开一个外挂最多能拦截多少导弹,开几个外挂才能打掉所有导弹
missile.cpp/in/out
输入输出格式
输入格式:
一行,依次为n颗导弹的高度(0<高度<2147483647)
输出格式:
第一行,一个外挂最多能拦截多少导弹;第二行,开几个外挂才能打掉所有导弹
输入输出样例
输入样例#1:
389 207 155 300 299 170 158 65
输出样例#1:
6
2
说明
n<=300000
思路:
这道题很容易就能发现是要求最长不上升子序列和最长下降子序列
所以单调栈求解轻松A掉
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std; int n,top,top2,h[],a[],h2[]; void add(int x)
{
int l=,r=top,m;
while(l<=r)
{
m=(l+r)>>;
if(x<=h[m]) l=m+;
else r=m-;
}
h[l]=x;
} void add2(int x)
{
int l=,r=top2,m;
while(l<=r)
{
m=(l+r)>>;
if(x>h2[m]) l=m+;
else r=m-;
}
h2[l]=x;
} int main()
{
n=;
while(scanf("%d",&a[n])!=EOF)n++;
n--;
memset(h,0x7f,sizeof(h));
for(int i=;i<=n;++i)
{
if(a[i]<=h[top]) h[++top]=a[i];
else add(a[i]);
}
for(int i=;i<=n;++i)
{
if(a[i]>h2[top2]) h2[++top2]=a[i];
else add2(a[i]);
}
printf("%d\n%d",top,top2);
}