Live2D

[HAOI2007]上升序列(最长上升子序列)

题目描述

对于一个给定的 S=\{a_1,a_2,a_3,…,a_n\}S={a1,a2,a3,,an} ,若有 P=\{a_{x_1},a_{x_2},a_{x_3},…,a_{x_m}\}P={ax1,ax2,ax3,,axm} ,满足 (x_1<x_2<…<x_m)(x1<x2<<xm)且 (a_{x_1}<a_{x_2}<…<a_{x_m})(ax1<ax2<<axm) 。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。

任务

给出 SS 序列,给出若干询问。对于第 ii 个询问,求出长度为 L_iLi 的上升序列,如有多个,求出字典序最小的那个(即首先 x_1x1 最小,如果不唯一,再看 x_2x2 最小……),如果不存在长度为 L_iLi 的上升序列,则打印Impossible.

输入输出格式

输入格式:

第一行一个 NN ,表示序列一共有 NN 个元素

第二行 NN 个数,为 a_1, a_2 , \cdots , a_na1,a2,,an

第三行一个 MM ,表示询问次数。下面接 MM 行每行一个数 LL ,表示要询问长度为 LL 的上升序列。

输出格式:

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

思路:

题意很简单,求字典序最小的长度为lis

但这道题要你输出求得的lis,所以我们要反着求lis(否则你会和我一开始一样一直wa)

我们的dp数组表示从这项开始,向后的最长上升子序列的长度

查询的时候,按从小到大遍历,满足上升就输出

代码(请无视注释,那是我一开始的代码):

#include<iostream>
#include<cstdio>
#define rii register int i
#define rij register int j
using namespace std;
int dp[10005],x[10005],pre[100005],maxn,ask,ans[10005],n,m;
int main()
{
    scanf("%d",&n);
    for(rii=1;i<=n;i++)
    {
        scanf("%d",&x[i]);
        dp[i]=1;
    }
    scanf("%d",&m);
    for(rii=n-1;i>=1;i--)
    {
        for(rij=i+1;j<=n;j++)
        {
            if(x[j]>x[i])
            {
                if(dp[j]+1>dp[i])
                {
                    dp[i]=dp[j]+1;
                }
            }
        }
        maxn=max(maxn,dp[i]);
//        if(maxn>imax)imax=maxn;
    }
//    for(rii=2;i<=n;i++)
//    {
//        for(rij=1;j<=i-1;j++)
//        {
//            if(x[i]>x[j])
//            {
//                if(dp[i]<dp[j]+1)
//                {
//                    dp[i]=dp[j]+1;
//                    pre[i]=j;
//                }
//            }
//        }
//        maxn=max(maxn,dp[i]);
//    }
    for(rii=1;i<=m;i++)
    {
        scanf("%d",&ask);
        if(ask>maxn)
        {
            puts("Impossible");
            continue;
        }
        int wz=ask;
        int pre=-19260817;
        for(rij=1;j<=n;j++)
        {
            if(dp[j]>=wz&&x[j]>pre)
            {
                printf("%d ",x[j]);
                pre=x[j];
                wz--;
                if(wz==0)
                {
                    break;
                }
            }
        }
//        for(rii=1;i<=n;i++)
//        {
//            if(dp[i]==ask)
//            {
//                wz=i;
//                break;
//            }
//        }
//        ans[ask]=x[wz];
//        int ltt=ask;
//        int kkk=pre[wz];
//        while(ltt--)
//        {
//            ans[ltt]=x[kkk];
//            kkk=pre[kkk];
//        }
//        for(rij=1;j<=ask;j++)
//        {
//            printf("%d ",ans[j]);    
//        }
        puts("");
    }
}

 

posted @ 2018-08-01 15:06  ztz11  阅读(562)  评论(0编辑  收藏  举报