码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1046 上升序列

时间:2015-02-16 12:55:50      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

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

 

Source

 

这题是对单调队列求最长上升序列的应用。

由于要求字典序最小的,我们得反过来求最长最长下降子序列(从末尾dp起)。g[i]表示从末尾起长度为i的最长下降子序列的第i为的最大值,f[i]表示从i开头的最长上升子序列的长度,len表示当前从末尾开始最长下降序列的长度。很明显,对于序列中的每一位s[i],我们可以在g中二分出最大的一个i使得大于g[i]>s[i](g具有单调性),之后f[i]=i+1,g[i+1]=s[i],len=max(len,i+1)。

最后输出长度为a序列时,我们可以从前往后扫。

技术分享
1 int cur = -(1<<30);
2 for (int i = 1;a;++ i)
3     if (f[i] >= a && s[i] > cur)
4     {
5         --a; cur = s[i]; printf("%d",s[i]);
6         if (a) putchar( );
7     }
View Code

 

技术分享
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 #define maxn 10010
 7 int f[maxn],g[maxn],s[maxn],n,len;
 8 
 9 inline int find(int k)
10 {
11     int l = 1,r = len,mid;
12     while (l <= r)
13     {
14         mid = (l + r) >> 1;
15         if (k >= g[mid]) r = mid - 1;
16         else l = mid + 1;
17     }
18     return l;
19 }
20 
21 inline void ready()
22 {
23     for (int i = n;i;--i)
24     {
25         int pos = find(s[i]);
26         f[i] = pos; len = max(pos,len); g[pos] = s[i];
27     }
28 }
29 
30 int main()
31 {
32     scanf("%d",&n);
33     for (int i = 1;i <= n;++i) scanf("%d",s+i);
34     ready();
35     int T,a; scanf("%d",&T);
36     while (T--)
37     {
38         scanf("%d",&a);
39         if (a > len) puts("Impossible");
40         else
41         {
42             int cur = -(1<<30);
43             for (int i = 1;a;++ i)
44                 if (f[i] >= a && s[i] > cur)
45                 {
46                     --a; cur = s[i]; printf("%d",s[i]);
47                     if (a) putchar( );
48                 }
49             putchar(\n);
50          }
51     }
52 }
View Code

 

BZOJ 1046 上升序列

标签:

原文地址:http://www.cnblogs.com/mmlz/p/4293921.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!