zoukankan      html  css  js  c++  java
  • BZOJ 1046: [HAOI2007]上升序列【贪心+二分状态+dp+递归】

    1046: [HAOI2007]上升序列

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4987  Solved: 1732
    [Submit][Status][Discuss]

    Description

      对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax
    2 < … < axm)。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。任务给
    出S序列,给出若干询问。对于第i个询问,求出长度为Li的上升序列,如有多个,求出字典序最小的那个(即首先
    x1最小,如果不唯一,再看x2最小……),如果不存在长度为Li的上升序列,则打印Impossible.

    Input

      第一行一个N,表示序列一共有N个元素第二行N个数,为a1,a2,…,an 第三行一个M,表示询问次数。下面接M
    行每行一个数L,表示要询问长度为L的上升序列。N<=10000,M<=1000

    Output

      对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.

    Sample Input

    6
    3 4 1 2 3 6
    3
    6
    4
    5

    Sample Output

    Impossible
    1 2 3 6
    Impossible

    HINT

    Source

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046

    分析:首先求出以每个数为开头上升序列长度,即倒着做最长下降子序列

    然后,把字典序尽量小的放前面

    即若要求的序列长度为x,如果以第一个数(字典序最小的数)开头的最长上升子序列大等于x,则将它放在答案第一个,第二个数开头小于x,则舍弃,第三个大于x-1,放答案第二个,以此类推!

    下面给出AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 inline int read()
     4 {
     5     int x=0,f=1;
     6     char ch=getchar();
     7     while(ch<'0'||ch>'9')
     8     {
     9         if(ch=='-')
    10             f=-1;
    11         ch=getchar();
    12     }
    13     while(ch>='0'&&ch<='9')
    14     {
    15         x=x*10+ch-'0';
    16         ch=getchar();
    17     }
    18     return x*f;
    19 }
    20 int n,m,cnt;
    21 const int N=100010;
    22 int a[N],f[N],best[N];
    23 inline void solve(int x)
    24 {
    25     int last=0;
    26     for(int i=1;i<=n;i++)
    27     {
    28         if(f[i]>=x&&a[i]>last)
    29         {
    30             printf("%d",a[i]);
    31             if(x!=1)
    32                 printf(" ");
    33             last=a[i];
    34             if(!(--x))
    35                 break;
    36         }
    37     }
    38     printf("
    ");
    39 }
    40 inline int find(int x)
    41 {
    42     int l=1,r=cnt,ans=0;
    43     while(l<=r)
    44     {
    45         int mid=(l+r)/2;
    46         if(best[mid]>x)
    47             ans=mid,l=mid+1;
    48         else
    49             r=mid-1;
    50     }
    51     return ans;
    52 }
    53 inline void pre()
    54 {
    55     for(int i=n;i;i--)
    56     {
    57         int t=find(a[i]);
    58         f[i]=t+1;
    59         cnt=max(cnt,t+1);
    60         if(best[t+1]<a[i])
    61             best[t+1]=a[i];
    62     }
    63 }
    64 int main()
    65 {
    66     n=read();
    67     for(int i=1;i<=n;i++)
    68         a[i]=read();
    69     pre();
    70     m=read();
    71     for(int i=1;i<=m;i++)
    72     {
    73         int x=read();
    74         if(x<=cnt)
    75             solve(x);
    76         else
    77             printf("Impossible
    ");
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    【原生】数组去重的方法
    【原生】详解Javascript中prototype属性(推荐)
    【原生】 ES5中的构造函数与 ES6 中的类 及构造函数的理解
    【react】React学习:状态(State) 和 属性(Props)
    【react】 flux 了解
    【请求数据】fetch 的get请求和post请求
    【react】 使用create-react-app创建react项目,运行npm run eject报错: 暴露webpack配置文件
    package.json 文件的介绍
    802.11协议精读1:学习资料整理(转)
    ns2之包结构解析
  • 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/7305142.html
Copyright © 2011-2022 走看看