Description
对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax
2 < … < axm)。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。任务给
出S序列,给出若干询问。对于第i个询问,求出长度为Li的上升序列,如有多个,求出字典序最小的那个(即首先
x1最小,如果不唯一,再看x2最小……),如果不存在长度为Li的上升序列,则打印Impossible.
Input
第一行一个N,表示序列一共有N个元素第二行N个数,为a1,a2,…,an 第三行一个M,表示询问次数。下面接M
行每行一个数L,表示要询问长度为L的上升序列。N<=10000,M<=1000
Output
对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.
Sample Input
6
3 4 1 2 3 6
3
6
4
5
3 4 1 2 3 6
3
6
4
5
Sample Output
Impossible
1 2 3 6
Impossible
1 2 3 6
Impossible
题解
比较暴力...
首先做一般的 $lis$ 都可以获得一个数组,如 $f_i$ 表示 $i$ 这个位置以前以 $a_i$ 结尾的最长上升子序列的长度。
我们考虑反着做,记 $f_i$ 表示 $i$ 这个位置之后以 $a_i$ 开头的最长上升子序列的长度。
然后处理询问 $len$ 的时候只需要从 $1$ 到 $n$ 扫一遍,记 $last$ 为上一个选出的数, $x$ 为待选序列长度。如果 $a_i > last$ 且 $f_i geq x$ ,便选上,将 $x-1$ 。
1 //It is made by Awson on 2018.1.4 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define LD long double 17 #define Max(a, b) ((a) > (b) ? (a) : (b)) 18 #define Min(a, b) ((a) < (b) ? (a) : (b)) 19 using namespace std; 20 const int N = 10000; 21 const int INF = ~0u>>1; 22 23 int n, m, a[N+5], f[N+5], w[N+5], x, maxlen; 24 25 void print(int x) { 26 int last = 0; 27 for (int i = 1; i <= n; i++) { 28 if (f[i] >= x && last < a[i] && x) { 29 if (last != 0) printf(" "); 30 last = a[i]; 31 printf("%d", a[i]); 32 x--; 33 } 34 } 35 printf(" "); 36 } 37 int dev(int l, int r, int val) { 38 int ans = 0; 39 while (l <= r) { 40 int mid = (l+r)>>1; 41 if (w[mid] > val) l = mid+1, ans = mid; 42 else r = mid-1; 43 } 44 return ans; 45 } 46 void work() { 47 scanf("%d", &n); w[0] = INF; 48 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 49 for (int i = n; i >= 1; i--) { 50 int pos = dev(0, maxlen, a[i]); maxlen = Max(maxlen, pos+1); 51 f[i] = pos+1; 52 if (f[i] == maxlen) w[maxlen] = a[i]; 53 else w[f[i]] = Max(w[f[i]], a[i]); 54 } 55 scanf("%d", &m); 56 while (m--) { 57 scanf("%d", &x); 58 if (x > maxlen) printf("Impossible "); 59 else print(x); 60 } 61 } 62 int main() { 63 work(); 64 return 0; 65 }