[bzoj1046][HAOI2007]上升序列【dp】

【题目链接】
  http://www.lydsy.com/JudgeOnline/problem.php?id=1046
【题解】
  记f[i]为从第i个往后的上升序列的最长长度。
  那么每遇到一个询问:将数列从前往后扫一遍,若f[i]>L则选了i之后一定能构造出一个合法的序列,为了保证字典序最小,i一定会在最后的答案中。所以将a[i]加入答案并将L1
  复杂度O(nlog2n+nm)

/* --------------
    user Vanisher
    problem
----------------*/
# include <bits/stdc++.h>
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    N       10010
using namespace std;
int read(){
    int tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
int a[N],h[N],f[N],n,m,k;
int main(){
    n=read();
    for (int i=1; i<=n; i++) 
        a[i]=read();
    int now=0;
    h[0]=inf;
    for (int i=n; i>=1; i--){
        int pl=0, pr=now, can;
        while (pl<=pr){
            int mid=(pl+pr)/2;
            if (h[mid]>a[i]){
                pl=mid+1;
                can=mid;
            }
            else pr=mid-1;
        }
        f[i]=can+1;
        h[can+1]=a[i];
        now=max(can+1,now);
    } 
    m=read();
    for (int i=1; i<=m; i++){
        k=read(); bool flag=false;
        int las=-inf;
        for (int i=1,j=1; i<=n&&j<=k; i++){
            if (f[i]>=(k-j+1)&&las<a[i]){
                flag=true;
                if (j==1) printf("%d",a[i]);
                    else printf(" %d",a[i]);
                j++;
                las=a[i];
            }
        }
        if (flag==false)
            printf("Impossible");
        printf("\n");
    }
    return 0;
}
posted @ 2018-03-07 18:38  Vanisher  阅读(65)  评论(0编辑  收藏  举报