【单调栈】最长不上升子序列变式,洛谷 P2757 导弹的召唤
题目背景
xxx今天玩使命召唤,被敌军用空对地导弹轰炸,很不爽;众所周知,xxx很不老实,他开了外挂;
外挂第一次可以打掉任意高度的导弹,之后每一次都不能打掉大于上一次高度的导弹;
但xxx水平太差,敌军最多有300000颗导弹,导弹只能按顺序打,因为外挂有BUG,而且是超音速导弹,只有一秒导弹就到了,只能编程解决;
但xxx上课不认真,平时帮他的sxy又不在,所以他只能求助于你
题目描述
有n颗导弹(n<=300000),求xxx开一个外挂最多能拦截多少导弹,开几个外挂才能打掉所有导弹
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[300101],a[300101],h2[300101]; void add(int x) { int l=1,r=top,m; while(l<=r) { m=(l+r)>>1; if(x<=h[m]) l=m+1; else r=m-1; } h[l]=x; } void add2(int x) { int l=1,r=top2,m; while(l<=r) { m=(l+r)>>1; if(x>h2[m]) l=m+1; else r=m-1; } h2[l]=x; } int main() { n=1; while(scanf("%d",&a[n])!=EOF)n++; n--; memset(h,0x7f,sizeof(h)); for(int i=1;i<=n;++i) { if(a[i]<=h[top]) h[++top]=a[i]; else add(a[i]); } for(int i=1;i<=n;++i) { if(a[i]>h2[top2]) h2[++top2]=a[i]; else add2(a[i]); } printf("%d\n%d",top,top2); }