【单调栈】最长不上升子序列变式,洛谷 P2757 导弹的召唤

时间:2024-04-20 16:55:32

题目背景

易琢然今天玩使命召唤,被敌军用空对地导弹轰炸,很不爽;众所周知,易琢然很不老实,他开了外挂;

外挂第一次可以打掉任意高度的导弹,之后每一次都不能打掉大于上一次高度的导弹;

但易琢然水平太差,敌军最多有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);
}