BZOJ1046【HAOI2007】上升序列 < DP >

Problem

【HAOI2007】上升序列

Time  Limit:  10  Sec\mathrm{Time\;Limit:\;10\;Sec}
Memory  Limit:  162  MB\mathrm{Memory\;Limit:\;162\;MB}

Description

对于一个给定的S=a1,a2,a3,,anS={a_1,a_2,a_3,\cdots,a_n},若有P=ax1,ax2,ax3,,axmP={a_{x_1},a_{x_2},a_{x_3},\cdots,a_{x_m}},满足(x1<x2<<xmx_1 < x_2 < \cdots< x_m)且(ax1<ax2<<axma_{x_1} < a_{x_2} < \cdots < a_{x_m})。那么就称PPSS的一个上升序列。如果有多个PP满足条件,那么我们想求字典序最小的那个。任务给出SS序列,给出若干询问。对于第ii个询问,求出长度为LiL_i的上升序列,如有多个,求出字典序最小的那个(即首先x1x_1最小,如果不唯一,再看x2x_2最小……),如果不存在长度为LiL_i的上升序列,则输出ImpossibleImpossible.

Input

第一行一个NN,表示序列一共有NN个元素第二行NN个数,为a1,a2,,ana_1,a_2,\cdots,a_n 第三行一个MM,表示询问次数。下面接MM行每行一个数LL,表示要询问长度为LL的上升序列。N10000N\le 10000M1000M\le 1000

Output

对于每个询问,如果对应的序列存在,则输出,否则输出ImpossibleImpossible.

Sample Input

1
2
3
4
5
6
6
3 4 1 2 3 6
3
6
4
5

Sample Output

1
2
3
Impossible
1 2 3 6
Impossible

标签:DP

Solution

一道LISLIS的变形。
显然需要先预处理出每个数向后能组成的LISLIS的最大长度。
对于每次询问,从前往后取,一旦某数字的LISLIS最大长度比lenlen大,则此数可加入答案。顺序构造即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cstdio>
#define MAX_N 10000
using namespace std;
int n, m, k, a[MAX_N+5], f[MAX_N+5];
void print() {
for (int i = 1, pre = 0; i <= n; i++)
if (f[i] >= k && a[i] > pre) {
printf("%d", a[i]), pre = a[i];
if (--k) printf(" ");
else break;
}
if (k) printf("Impossible"); printf("\n");
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), f[i] = 1;
for (int i = n; i >= 1; i--) for (int j = i+1; j <= n; j++) if (a[i] < a[j]) f[i] = max(f[i], f[j]+1);
scanf("%d", &m);
while (m--) scanf("%d", &k), print();
return 0;
}