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

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

/* --------------
    user Vanisher
    problem
----------------*/
# include 
# 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)&&lastrue;
                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;
}

你可能感兴趣的:([bzoj1046][HAOI2007]上升序列【dp】)