[bzoj1046][HAOI2007]上升序列【dp】
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1046
【题解】
记为从第个往后的上升序列的最长长度。
那么每遇到一个询问:将数列从前往后扫一遍,若则选了之后一定能构造出一个合法的序列,为了保证字典序最小,一定会在最后的答案中。所以将加入答案并将减。
复杂度
/* --------------
user Vanisher
problem
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define N 10010
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
int a[N],h[N],f[N],n,m,k;
int main(){
n=read();
for (int i=1; i<=n; i++)
a[i]=read();
int now=0;
h[0]=inf;
for (int i=n; i>=1; i--){
int pl=0, pr=now, can;
while (pl<=pr){
int mid=(pl+pr)/2;
if (h[mid]>a[i]){
pl=mid+1;
can=mid;
}
else pr=mid-1;
}
f[i]=can+1;
h[can+1]=a[i];
now=max(can+1,now);
}
m=read();
for (int i=1; i<=m; i++){
k=read(); bool flag=false;
int las=-inf;
for (int i=1,j=1; i<=n&&j<=k; i++){
if (f[i]>=(k-j+1)&&las<a[i]){
flag=true;
if (j==1) printf("%d",a[i]);
else printf(" %d",a[i]);
j++;
las=a[i];
}
}
if (flag==false)
printf("Impossible");
printf("\n");
}
return 0;
}