P1020 导弹拦截(nlogn求最长不下降子序列)

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是≤50000 \le 5000050000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出格式

输入格式:

111行,若干个整数(个数≤100000 \le 100000100000)

输出格式:

222行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入样例#1: 复制
389 207 155 300 299 170 158 65
输出样例#1: 复制
6
2

求最长不下降子序列需要做的是如果要插入的<=d[l]的数值 则直接插入 如果不是 则在d中找到第一个比他小的然后替换掉 这时候用到了upper_bound(d,d+l,greater<int>)-d;
从而就可以求出来
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<cmath>
#define Inf 0x3f3f3f3f

const int maxn=1e5+5;
typedef long long ll;
using namespace std;

int a[maxn];
int d[maxn],d2[maxn];
int main()
{
   int len=0;
   int x;
   while(scanf("%d",&x)!=EOF)
   {
         a[len++]=x;
   }
   d[0]=a[0];
   d2[0]=a[0]; 
   int l=0,l2=0;
   for(int t=1;t<len;t++)
   {
         if(a[t]<=d[l])
         {
             d[l+1]=a[t];
           l++;
      }
      else
      {
          int pos=upper_bound(d,d+l,a[t],greater<int>())-d;
          d[pos]=a[t]; 
      }
      if(a[t]>d2[l2])
      {
          d2[l2+1]=a[t];
          l2++;
      }
      else
      {
          int pos=lower_bound(d2,d2+l2,a[t])-d2;
          d2[pos]=a[t]; 
      }
   }
   cout<<l+1<<" "<<l2+1<<endl;
} 

猜你喜欢

转载自www.cnblogs.com/Staceyacm/p/11224600.html