首页 > 其他 > 详细

[bzoj1046][HAOI2007]上升序列

时间:2017-03-01 23:19:00      阅读:211      评论:0      收藏:0      [点我收藏+]

题意:对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax
2 < … < axm)。那么就称P为S的一个上升序列。

有m个询问,每次询问一个长度L,如果没有长度为L的上升序列,输出Impossible,要不然求一个字典序最小的上升序列。

(这题的字典序最小居然指的是下标)

n<=10000,m<=1000

题解:倒着dp,用线段树求出每个点和它后面最长的上升序列的长度。

然后构造的时候,从1开始,如果f[1]>=L 输出f[1],并且 L--   .......以此类推,可以保证是字典序最小的。

复杂度nlogn+nm

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 16384
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-) f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();}
    return x*f;
}

int n,cnt=0,m;
int l[10005],s[10005],f[10005];
int T[N*2+5];

void renew(int x,int ad)
{
    x+=N;T[x]=max(T[x],ad);
    for(x>>=1;x;x>>=1)T[x]=max(T[x<<1],T[(x<<1)+1]);
}

int query(int l,int r)
{
    int sum=0;if(l>n) return 0;
    for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1) sum=max(sum,T[l+1]);
        if( r&1) sum=max(sum,T[r-1]);
    }
    return sum;
}

int main()
{
    n=read();for(int i=1;i<=n;i++) s[i]=l[i]=read();
    sort(l+1,l+n+1);
    for(int i=1;i<=n;i++)if(l[i]!=l[i-1])l[++cnt]=l[i];
    for(int i=n;i;i--)
    {
        int x=lower_bound(l+1,l+cnt+1,s[i])-l;
        f[i]=query(x+1,cnt)+1;
        renew(x,f[i]);
    }
    int maxn=query(1,cnt);m=read();
    for(int i=1;i<=m;i++)
    {
        int x=read();if(x>maxn){puts("Impossible");continue;}
        for(int j=1,pre=0;x;j++)
            if(f[j]>=x&&s[j]>pre)
            {printf("%d",s[j]);x--;if(x)printf(" ");pre=s[j];}
        puts("");
    }
    return 0;
}

 

[bzoj1046][HAOI2007]上升序列

原文:http://www.cnblogs.com/FallDream/p/bzoj1046.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!