大概做法是这样的,N方的LIS求法。然后把输入的提问离线,从小到大排序。在dp的过程中,顺便解决答案。但是只有10分。。。具体代码如下:
#include<cstdio>
#include<algorithm>
const int MAXN = 1e4+5;
const int MAXM = 1e3+5;
const int INF = 0x3f3f3f3f;
using namespace std;
void readint(int &res){
res = 0;int f = 1;char ch = getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'){
f*=-1;
}
ch = getchar();
}
while(ch>='0'&&ch<='9'){
res = res*10+ch-'0';
ch = getchar();
}
res *= f;
return;
}
int N,M;
struct que{
int idx,k;
bool operator<(const que & q)const{
return k<q.k;
}
}ques[MAXM];
int ans[MAXM];
int dp[MAXN],pre[MAXN];//pre数组有点类似链表,存i是从哪个位置转移过来的。
int ora[MAXN];
int st[MAXN];
void print(int p){//输出第i个提问的答案
int top = 1,tail = 0;
for(int i = ans[p];i!=0;i=pre[i]){//因为链表是从后往前存的,所以写了个栈结构,把它从前往后输出。
st[++tail]=ora[i];
}
if(top>tail){
printf("Impossible\n");
return;
}
while(tail>=top){
printf("%d ",st[tail]);
tail--;
}
printf("\n");
return;
}
int main(){
readint(N);
for(int i = 1;i<=N;++i){
readint(ora[i]);
}
readint(M);
for(int i = 1;i<=M;++i){
readint(ques[i].k);
ques[i].idx = i;
}
sort(ques+1,ques+M+1);//把提问离线,排序。
int p = 1;//标记处理到第几个提问了,有点类似指针
for(int i = 1;i<=N;++i){
int mx = -INF;
for(int j = 0;j<i;++j){
if(dp[j]>mx&&ora[j]<ora[i]){
mx = dp[j];
dp[i]=dp[j]+1;
pre[i]=j;//pre数组有点类似链表,存i是从哪个位置转移过来的。
}
}//dp过程
while(p<=M){//处理答案
if(ques[p].k==dp[i]){
ans[ques[p].idx]=i;
++p;
}else{
break;
}
}
}
for(int i = 1;i<=M;++i){
print(i);
}
return 0;
}