【bzoj1046】[HAOI2007]上升序列

首先求出以每个数为开头上升序列长度,即倒着做最长下降子序列

然后,把字典序尽量小的放前面

即若要求的序列长度为x,如果以第一个数(字典序最小的数)开头的最长上升子序列大等于x,则将它放在答案第一个,第二个数开头小于x,则舍弃,第三个大于x-1,放答案第二个,以此类推

#include<algorithm>

#include<iostream>

#include<cstdlib>

#include<cstring>

#include<cstdio>

#include<cmath>

using namespace std;

typedef long long LL;

#ifdef WIN32

#define orz "%lld"

#else

#define orz "%I64d"

#endif

#define MAXN 10010

int f[MAXN],a[MAXN],b[MAXN];

int n,m;

int ans;

int x;

void work(int x)

{

    int res=0;

    for (int i=1;i<=n;i++)

        if (f[i]>=x && a[i]>res)

        {

            printf("%d",a[i]);

            if (x!=1)

                printf(" ");

            res=a[i];

            x--;

            if (!x)

                break;

        }

    printf("\n");

}

int find(int x)

{

    int l=1,r=ans,tmp=0;

    while (l<=r)

    {

        int m=(l+r)>>1;

        if (b[m]>x)

            tmp=m,l=m+1;

        else

            r=m-1;

    }

    return tmp;

}

void get()

{

    for (int i=n;i;i--)

    {

        int t=find(a[i]);

        f[i]=t+1;

        ans=max(ans,t+1);

        //b[t+1]=min(b[t+1],a[i]);

        if(b[t+1]<a[i])

            b[t+1]=a[i];

    }

}

int main()

{

    scanf("%d",&n);

    for (int i=1;i<=n;i++)

        scanf("%d",&a[i]);

    get();

    scanf("%d",&m);

    while (m--)

    {

        scanf("%d",&x);

        if (x<=ans)

            work(x);

        else

            printf("Impossible\n");

    }   

    return 0;

}

时间: 2024-12-31 05:21:39

【bzoj1046】[HAOI2007]上升序列的相关文章

[bzoj1046][HAOI2007]上升序列

题意:对于一个给定的S={a1,a2,a3,-,an},若有P={ax1,ax2,ax3,-,axm},满足(x1 < x2 < - < xm)且( ax1 < ax2 < - < axm).那么就称P为S的一个上升序列. 有m个询问,每次询问一个长度L,如果没有长度为L的上升序列,输出Impossible,要不然求一个字典序最小的上升序列. (这题的字典序最小居然指的是下标) n<=10000,m<=1000 题解:倒着dp,用线段树求出每个点和它后面最长

[BZOJ1046] [HAOI2007] 上升序列 (dp)

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的上升序列

【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列

nlogn求出最长上升子序列长度. 对每次询问,贪心地回答.设输入为x.当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] 即可. f[i]表示以a[i]开头的最长上升子序列长度. 但这个东西难以统计.so 我们将原序列反序,求f[i] 表示以 a[i]为结尾的最长下降子序列长度即可.最后再将f.a reverse一下. 1 #include<cstdio> 2 #include<algorithm> 3

[BZOJ1046][HAOI2007]上升序列 DP+贪心

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046 我们先求出对于每一个数字作为开头的LCS的长度f[i],最长的f[i]为mxlen. 对于每一个询问,我们选取答案,从第1个开始选.假设当前已经选到了第x个答案,我们只需要一直往后面找到第一个f[k]且f[k]+x>mxlen,它就是第x+1个答案. 这样时间复杂度就是$O(nm)$的,感觉玄学卡过…… 1 #include<cstdio> 2 #include<cs

BZOJ 1046: [HAOI2007]上升序列 LIS -dp

1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 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的一个上升序列.如果有多

【BZOJ】1046 : [HAOI2007]上升序列

1046: [HAOI2007]上升序列 题意:给定S={a1,a2,a3,…,an}问是否存在P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax2 < … < axm),若存在多组符合长度为m的递增子序列,则输出以序号字典序最小的:并非是数值 Sample Input 6 3 4 1 2 3 6 3 6 4 5 Sample Output Impossible 1 2 3 6 Impossible 数据范围 N&

【BZOJ 1046】 1046: [HAOI2007]上升序列

1046: [HAOI2007]上升序列 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

1046: [HAOI2007]上升序列(dp)

1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4999  Solved: 1738[Submit][Status][Discuss] Description 对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax2 < … < axm).那么就称P为S的一个上升序列.如果有多

【BZOJ 1046】 [HAOI2007]上升序列

1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2688  Solved: 891 [Submit][Status] Description 对于一个给定的S={a1,a2,a3,-,an},若有P={ax1,ax2,ax3,-,axm},满足(x1 < x2 < - < xm)且( ax1 < ax2 < - < axm).那么就称P为S的一个上升序列.如果有多个P满足条件,那

BZOJ 1046: [HAOI2007]上升序列(LIS)

题目挺坑的..但是不难.先反向做一次最长下降子序列.然后得到了d(i),以i为起点的最长上升子序列,接下来贪心,得到字典序最小. ------------------------------------------------------------------- #include<cstdio> #define rep(i,n) for(int i=0;i<n;++i) using namespace std; const int maxn=10005; const int inf=0