题目挺坑的..但是不难.先反向做一次最长下降子序列.然后得到了d(i),以i为起点的最长上升子序列,接下来贪心,得到字典序最小.
-------------------------------------------------------------------
#include<cstdio>
#define rep(i,n) for(int i=0;i<n;++i)
using namespace std;
const int maxn=10005;
const int inf=0x7fffffff;
int a[maxn];
int g[maxn];
int d[maxn];
int lowerBound(int l,int r,int v) {
int mid;
while(l<r) {
mid=l+(r-l)/2;
if(g[mid]<=v) r=mid;
else l=mid+1;
}
return l;
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int n,m;
scanf("%d",&n);
rep(i,n) { scanf("%d",&a[i]); g[i+1]=-inf; }
for(int i=n-1;i>=0;--i) {
int k=lowerBound(1,n,a[i]);
d[i]=k;
g[k]=a[i];
}
scanf("%d",&m);
while(m--) {
int l;
scanf("%d",&l);
if(g[l]==-inf) printf("Impossible");
else {
int last=-inf;
rep(i,n) if(d[i]>=l && a[i]>last) {
printf("%d",a[i]);
if(0==--l) break;
last=a[i];
printf(" ");
}
}
printf("\n");
}
return 0;
}
--------------------------------------------------------------------
1046: [HAOI2007]上升序列
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2843 Solved: 949
[Submit][Status][Discuss]
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.
Input
第一行一个N,表示序列一共有N个元素第二行N个数,为a1,a2,…,an 第三行一个M,表示询问次数。下面接M行每行一个数L,表示要询问长度为L的上升序列。
Output
对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.
Sample Input
6
3 4 1 2 3 6
3
6
4
5
Sample Output
Impossible
1 2 3 6
Impossible
HINT
数据范围
N<=10000
M<=1000