UESTC_导弹拦截 2015 UESTC Training for Dynamic Programming<Problem N>

N - 导弹拦截

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都要高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹,同时,司令部想知道拦截下来的导弹的高度。拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹。

Input

第一行是一个整数t,代表case数。 对于每一个case,第一行是一个整数n(1n100000); 第二行是n个非负整数,表示第n枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。数据保证高度不会超过100000.

Output

对于每一个case,第一行输出最多能拦截的导弹数,第二行按来袭顺序输出拦截下来的导弹的高度构成的序列,以一个空格隔开。若有不止一种方法可以拦截最多的导弹,输出字典序最小的。

Sample input and output

Sample InputSample Output
1
5
1 6 3 5 7
4
1 3 5 7

 

解题报告:

首先我们令 c[i] 表示长度为 i 的上升子序列中最后一位最小的.可以注意到,c数组是单调不减的,我们每次都可二分求解.

之后我们考虑如何输出答案,从后往前扫,依次匹配长度为 x ,x – 1 , x – 2 ….为结尾的上升子序列,每次需要前面一个数小于后面一个数即可.

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <stack>
using namespace std;
const int maxn = 1e5 + 50;
int h[maxn],n,c[maxn],maxlength,f[maxn];
stack<int>s;
/*
贪心dp
 c[i] -> 长度为 i 的最长上升子序列中的最小的最后一位
*/


int main(int argc,char *argv[])
{
  int Case;
  scanf("%d",&Case);
  c[0] = 0;
  while(Case--)
   {
         memset(c,-1,sizeof(c));
         scanf("%d",&n);
         for(int i = 0 ; i < n ; ++ i ) scanf("%d",h + i);
         c[1] = h[0] , maxlength = 1 , f[0] = 1;
         for(int i = 1 ; i < n ; ++ i)
          {
             int pos = lower_bound(c+1,c+maxlength+1,h[i]) - c;
             if (c[pos] == -1 || c[pos] > h[i])
              c[pos] = h[i];
             f[i] = pos;
             maxlength = max(maxlength,f[i]);
       }
      printf("%d\n",maxlength);
      int need = maxlength , pre = 1 << 20;
      for(int i = n - 1 ; i >= 0 ; -- i) //遍历 ,尽可能小 
       {
             if (f[i]  == need && h[i] < pre)
              {
                 need--;
              pre = h[i];
              s.push(h[i]);
           }
       }
      printf("%d",s.top());s.pop();
      while(!s.empty())
       {
            printf(" %d",s.top());
            s.pop();
       }
      printf("\n");
   }
  return 0;
}

 

转载于:https://www.cnblogs.com/Xiper/p/4539652.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
互联网络程序设计是指在互联网上进行程序开发和设计的过程。UESTC则是我国的一所著名高校——电子科技大学。 互联网络程序设计 uestc包含了两个主要的方面:互联网络和程序设计。互联网络是指将多个计算机网络通过通信链路互相连接起来,实现信息共享和资源共享的网络系统。程序设计是指根据需求和目标,通过编写代码和设计算法,实现计算机程序的过程。 互联网络程序设计 uestc的学习内容主要包括以下几个方面: 1. 网络知识:学习互联网络的基本概念、原理和协议,如TCP/IP协议、HTTP协议等。掌握网络编程的基本技术,能够编写网络应用程序。 2. 数据通信:学习数据通信的基本原理和技术,包括数据传输的方式、数据压缩和加密等。了解网络安全和数据保护的基本知识。 3. 程序设计:学习编程语言和开发工具,如Java、C++和Python等。掌握常用的编程技巧和方法,能够设计和实现复杂的网络应用程序。 4. Web开发:学习Web开发的基本知识和技术,包括HTML、CSS、JavaScript等。能够设计和实现交互式的Web应用程序。 5. 数据库技术:学习数据库的基本原理和技术,如SQL语言和数据库管理系统。能够设计和管理数据库,实现数据的存储和检索。 通过学习互联网络程序设计 uestc,可以掌握互联网应用开发的基本技能,具备设计和实现网络应用程序的能力。这对于目前互联网行业的人才需求来说是非常重要的,也为学生提供了广阔的就业和创业机会。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值