洛谷 2757 导弹的召唤 DP 解题报告

来源:互联网 发布:java趣味编程100例下载 编辑:程序博客网 时间:2024/04/28 19:37

题目背景

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

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

但易琢然水平太差,敌军最多有300000颗导弹,导弹只能按顺序打,因为外挂有BUG,而且是超音速导弹,只有一秒导弹就到了,只能编程解决;

但易琢然上课不认真,平时帮他的sxy又不在,所以他只能求助于你

题目描述

有n颗导弹(n<=300000),求易琢然开一个外挂最多能拦截多少导弹,开几个外挂才能打掉所有导弹

输入输出格式

输入格式:

一行,依次为n颗导弹的高度(0<高度<2147483647)

输出格式:

第一行,一个外挂最多能拦截多少导弹;第二行,开几个外挂才能打掉所有导弹

输入输出样例

输入样例#1:

389 207 155 300 299 170 158 65

输出样例#1:

6
2

说明

n<=300000

思路

第一次最长下降,第二次最长上升

代码

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>using namespace std;const int N=300000+5;int n,tot,a[N],q[N];int fdown(int x){    int l=1,r=tot,mid;    while (l<=r)    {        mid=(l+r)/2;        if (q[mid]>=x) l=mid+1;        else r=mid-1;    }    return l;}int fup(int x){    int l=1,r=tot,mid;    while (l<=r)    {        mid=(l+r)/2;        if (x>q[mid]) l=mid+1;        else r=mid-1;    }    return l;}int main(){    while (~scanf("%d",&a[n+1])) n++;    tot=0;    for (int i=1;i<=n;i++)    {        int p=fdown(a[i]);        q[p]=a[i];        if (p>tot) tot=p;    }    printf("%d\n",tot);    memset(q,0,sizeof(q));    tot=0;    for (int i=1;i<=n;i++)    {        int p=fup(a[i]);        q[p]=a[i];        if (p>tot) tot=p;    }    printf("%d\n",tot);    return 0;}
原创粉丝点击