题解:
首先求出以每个数为开头上升序列长度,即倒着做最长下降子序列
然后,把字典序尽量小的放前面
即若要求的序列长度为x,如果以第一个数(字典序最小的数)开头的最长上升子序列大等于x,则将它放在答案第一个,第二个数开头小于x,则舍弃,第三个大于x-1,放答案第二个,以此类推。
Code:
C
o
d
e
:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,m,cnt;
int a[N],f[N],q[N];
void solve(int x)
{
int last=0;
for(int i=1;i<=n;i++)
if(f[i]>=x&&a[i]>last)
{
printf("%d",a[i]);
if(x!=1)printf(" ");
last=a[i];
x--;
if(!x)break;
}
printf("\n");
}
int find(int x)
{
int l=1,r=cnt,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(q[mid]>x)ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=n;i;i--)
{
int t=find(a[i]);
f[i]=t+1;
cnt=max(cnt,t+1);
if(q[t+1]<a[i])q[t+1]=a[i];
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
if(x<=cnt)solve(x);
else puts("Impossible");
}
return 0;
}