首先求出以每个数为开头上升序列长度,即倒着做最长下降子序列
然后,把字典序尽量小的放前面
即若要求的序列长度为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;
}