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的上升序列,则打印Impossible.
【题目分析】
蒟蒻看错题了,动态规划。
【代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int a[10001],f[10001],g[10001],n,q,maxx;
void solve(int x)
{
int lst=0;
for (int i=1;i<=n;++i)
if (f[i]>=x&&a[i]>lst)
{
// printf("x is %d\n",x);
printf("%d%c",a[i],x--==1?'\n':' ');
lst=a[i];
// x--;
if (!x) return;
}
}
void pre()
{
memset(g,0,sizeof g);
g[0]=0x3f3f3f3f;
f[n]=1;
g[1]=a[n];
for (int i=n-1;i>=1;--i)
{
// printf("now g is :\n");
// for (int j=0;j<=n;++j) printf("%d ",g[j]);
// printf("\n");
// printf("test on %d\n",i);
int l=0,r=n;
while (l<r)
{
// printf("Binary %d %d\n",l,r);
int mid=(l+r)/2+1;
// printf("mid is %d\n",mid);
if (g[mid]>a[i]) l=mid;
else r=mid-1;
}
// printf("on %d\n",l+1);
f[i]=l+1;
maxx=max(l+1,maxx);
g[l+1]=a[i];
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
pre();
// for (int i=1;i<=n;++i) printf("%d\n",f[i]);
scanf("%d",&q);
for (int i=1;i<=q;++i)
{
int x;
scanf("%d",&x);
if (x<=maxx) solve(x);
else printf("Impossible\n");
}
}