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

    1046: [HAOI2007]上升序列

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3438  Solved: 1171
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    6
    3 4 1 2 3 6
    3
    6
    4
    5

    Sample Output

    Impossible
    1 2 3 6
    Impossible

    HINT

    数据范围

    N<=10000

    M<=1000

    Source

    题解:

       我们建立P[i] 表示 从i位置开始到n位置的最长上升子序列数

     这个就是A数组反过来求一遍就好了

    //meek///#include<bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <set>
    #include <stack>
    #include <sstream>
    #include <vector>
    using namespace std ;
    #define mem(a) memset(a,0,sizeof(a))
    #define pb push_back
    #define fi first
    #define se second
    #define MP make_pair
    typedef long long ll;
    
    const int N = 100005;
    const int inf = 99999999;
    const int mod= 1000000007;
    
    int p[N],a[N],b[N],n,dp[N];
    int main() {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            b[n-i+1] = -a[i];
        }
        fill(dp+1,dp+n+1,inf);
        for(int i=1;i<=n;i++) {
            int tmp=lower_bound(dp+1,dp+n+1,b[i])-dp;
            p[n-i+1] = tmp;
            dp[tmp] = b[i];
        }
        //for(int i=1;i<=n;i++) cout<<p[i]<<" ";
        int L = lower_bound(dp+1,dp+n+1,inf) - dp;
        L--;
        int m,x;
        scanf("%d",&m);
        while(m--) {
            scanf("%d",&x);
            if(x>L) {
                cout<<"Impossible"<<endl;
                continue;
            }
            int last=-1;
            for(int i=1;i<=n;i++) {
                if(p[i] >= x && a[i] > last) {
                    printf("%d",a[i]);last = a[i];
                    if(!(--x)) {
                        cout<<endl;
                        break;
                    }cout<<" ";
                }
            }
        }
        return 0;
    }
    代码
  • 相关阅读:
    Android开发(十五)-Service和BroadcastReceiver
    Android开发(十四)-ContentProvider数据共享
    Android开发(十三)-图形与图像处理
    Android开发(十二)-Android应用资源
    Android开发(十一)-Intent和IntentFilter通信
    Android开发(十)-Activity和Fragment
    Android开发(九)-事件机制
    模拟面试
    二叉堆
    面试
  • 原文地址:https://www.cnblogs.com/zxhl/p/5065177.html
Copyright © 2011-2022 走看看