zoukankan      html  css  js  c++  java
  • 1046: [HAOI2007]上升序列(dp)

    1046: [HAOI2007]上升序列

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4999  Solved: 1738
    [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
     
    /*
    我们知道nlogn的最长上升子序列中定义状态f[i]表示以i结尾的...
    这个题要求以i开头的 所以倒着做最长下降子序列就好了,f只记录长度 
    所以需要有个best数组存序列
    最后输出答案,若要求的序列长度为x,如果以第一个数(字典序最小的数)
    开头的最长上升子序列大等于x,则将它放在答案第一个,
    第二个数开头小于x,则舍弃,第三个大于x-1,放答案第二个,以此类推 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    #define inf 1000000000
    #define N 100007
    
    using namespace std;
    int n,m,cnt;
    int a[N],f[N],best[N];
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void solve(int x)
    {
        int last=0;
        for(int i=1;i<=n;i++)
            if(f[i]>=x&&a[i]>last)
            {
                printf("%d",a[i]);
                if(x!=1)printf(" ");
                last=a[i];x--;
                if(!x)break;
            }printf("
    ");
    }
    
    int find(int x)
    {
        int l=1,r=cnt,ans=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(best[mid]>x)ans=mid,l=mid+1;
            else r=mid-1;
        }return ans;
    }
    
    void dp()
    {
        for(int i=n;i;i--)
        {
            int t=find(a[i]);
            f[i]=t+1;cnt=max(cnt,t+1);
            if(best[t+1]<a[i]) best[t+1]=a[i];
        }
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        dp(); m=read();
        for(int i=1;i<=m;i++)
        {
            int x=read();
            if(x<=cnt)solve(x);
            else puts("Impossible");
        }
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    响应式一些知识
    自动显示git分支--安装oh-my-zsh(Ubuntu环境)
    一些感受吧
    vim 编辑器笔记
    gitlab 配置 ssh && ubuntu
    css3遇到的一些属性
    ajax 基础教程
    怎么查看浏览器内核
    简单理解锁
    测试项目注意项
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7392125.html
Copyright © 2011-2022 走看看