bzoj1046 [HAOI2007]上升序列——LIS

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1046

倒序求最长下降子序列,则得到了每个点开始的最长上升子序列;

然后贪心输出即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=10005,inf=0x7fffffff;
int n,m,l,a[maxn],b[maxn],len[maxn],cnt;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    a[b[0]]=inf;
    for(int i=n;i;i--)
    {
        if(a[b[cnt]]>a[i])
        {
            b[++cnt]=i;len[i]=cnt;
            continue;
        }
        int l=1,r=cnt,res;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(a[b[mid]]>a[i])l=mid+1;
            else r=mid-1,res=mid;
        }
        b[res]=i;len[i]=res;//i而非a[i]! 
    }
    scanf("%d",&m);
    for(int j=1;j<=m;j++)
    {
        scanf("%d",&l);
        if(cnt<l)
        {
            printf("Impossible\n");continue;
        }
        int nw=-inf;
        for(int i=1;i<=n;i++)
            if(len[i]>=l&&a[i]>nw)
            {
                printf("%d ",a[i]);
                nw=a[i];l--;
                if(!l)break;
            }
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-06-06 20:38  Zinn  阅读(155)  评论(0编辑  收藏  举报