【单调栈】最长不上升子序列变式,洛谷 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);
}

 

posted @ 2017-05-04 18:55  减维  阅读(205)  评论(0编辑  收藏  举报