题目
魔法世界为了防御修罗王军团的导弹袭击,开发出一种导弹拦截系统---“要你命3000”。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天。雷达朴拙到修罗王军团的导弹来袭。有意该系统还在试用阶段,所以只有一套系统,一次有可能不能拦截所有的导弹。
第一行输入一个n,n代表有多少发炮弹,第二行依次输入n个炮弹飞来的高度,计算这套系统最多能拦截多少炮弹和如果要拦截所有炮弹最少要配备多少套这种导弹拦截系统。
输入样例
8
389 207 155 300 299 170 158 65
输出样例
6 2
解题思路
分别求一次最长下降子序列和最长上升子序列的长度,时间复杂度2nlogn
代码
#include <cstdio>
#include <cstring>uu
#include <iostream>
#include <algorithm>
using namespace std ;
const int maxn = 1000 + 10 ;
int a[maxn] , mark[maxn] , len ;
int tofind(int x)
{
int l = 1 , r = len , mid ;
while(l <= r)
{
mid = (l + r) >> 1 ;
if(mark[mid] < x)
l = mid + 1;
else
r = mid - 1 ;
}
return l ;
}
int main()
{
int n ;
while(scanf("%d" , &n) != EOF)
{
for(int i = 1 ; i <= n ; i++)
{
scanf("%d" , &a[i]) ;
}
len = 1 ;
mark[len] = a[len] ;
for(int i = 2 ; i <= n ; i++)
{
if(a[i] > mark[len])
{
mark[++len] = a[i] ;
}
else
{
int findpos = tofind(a[i]) ;
mark[findpos] = a[i] ;
}
}
int tmp = len ;
reverse(a + 1 , a + n + 1) ;
len = 1 ;
mark[len] = a[len] ;
for(int i = 2 ; i <= n ; i++)
{
if(a[i] > mark[len])
{
mark[++len] = a[i] ;
}
else
{
int findpos = tofind(a[i]) ;
mark[findpos] = a[i] ;
}
}
printf("%d %d\n" , len, tmp) ;
}
return 0 ;
}