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

    1046: [HAOI2007]上升序列

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 5290  Solved: 1831
    [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

    题解:

      好久没有写博客了,最近考试比较多……

      这个题目我们肯定是想着如果求出以i开头的最长上升子序列的长度就好了,有了这个数组我们就显然可以打印出整个序列了。

      所以我们考虑倒着dp出以i开头的最长下降子序列的长度,那么就是上面写的正着的以i开头的最长上升子序列的长度,dp的时候写一颗值域线段树优化一下就可以了。

      然后我们怎么打印呢,检查一下最优子结构就可以了,从第一位开始,当前要求长度为x,如果dp[i]>=x&&v[i]>上一位所选的数,那么这个数就是合法的,并且一定是最优的,我们将x--,表示,因为已经选了一位了,下一位就只需要长度为x-1就可以了。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #define MAXN 101000
    using namespace std;
    int dp[MAXN];
    int v[MAXN],b[MAXN];
    struct tree{
        int l,r,mx;
    }a[MAXN*4];
    int n,q;
    
    void build(int xv,int l,int r){
        if(l==r){
            a[xv].l=l,a[xv].r=r;
            a[xv].mx=0;
            return;
        }
        a[xv].l=l,a[xv].r=r;
        int mid=(l+r)/2;
        build(xv*2,l,mid),build(xv*2+1,mid+1,r);
        a[xv].mx=max(a[xv*2].mx,a[xv*2+1].mx);
    }
    
    int query(int xv,int l,int r){
        int L=a[xv].l,R=a[xv].r,mid=(L+R)/2;
        if(l==L&&r==R){
            return a[xv].mx;
        }
        if(r<=mid) return query(xv*2,l,r);
        else if(l>mid) return query(xv*2+1,l,r);
        return max(query(xv*2,l,mid),query(xv*2+1,mid+1,r));
    }
    
    void insert(int xv,int ps,int x){
        int l=a[xv].l,r=a[xv].r,mid=(l+r)/2;
        if(l==r){
            a[xv].mx=max(a[xv].mx,x);
            return;
        }
        if(ps<=mid) insert(xv*2,ps,x);
        else insert(xv*2+1,ps,x);
        a[xv].mx=max(a[xv*2].mx,a[xv*2+1].mx);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&v[i]);b[i]=v[i];
        }
        sort(b+1,b+n+1);
        int k=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++){
            v[i]=lower_bound(b+1,b+k+1,v[i])-b;
        }
        build(1,1,k+1);
        for(int i=n;i>=1;i--){
            dp[i]=query(1,v[i]+1,k+1)+1;
            insert(1,v[i],dp[i]);
        }
        scanf("%d",&q);
        while(q--){
            int x;scanf("%d",&x);
            int minn=0;
            for(int i=1;i<=n;i++){
                if(dp[i]>=x&&v[i]>minn) {
                    if(x==1) printf("%d",b[v[i]]);
                    else printf("%d ",b[v[i]]);x--,minn=v[i];
                }
                if(x==0) break;
            }
            if(x!=0){
                printf("Impossible");
            }
            puts("");
        }
        return 0;
    }

     

  • 相关阅读:
    jmeter(46) redis
    jmeter(45) tcp/ip协议
    Codeforces Round #538 (Div. 2)D(区间DP,思维)
    Codeforces Global Round 1D(DP,思维)
    Educational Codeforces Round 57D(DP,思维)
    UPC11073(DP,思维)
    Yahoo Progamming Contest 2019D(DP,思维)
    Atcoder Beginner Contest 118D(DP,完全背包,贪心)
    Xuzhou Winter Camp 1C(模拟)
    Educational Codeforces Round 57 (Rated for Div. 2)D(动态规划)
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7695546.html
Copyright © 2011-2022 走看看