BZOJ1046 [HAOI2007]上升序列

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

Sample Output

Impossible
1 2 3 6
Impossible
 
 
 
正解:DP+贪心

解题报告:

  其实挺水的却花了我半个多小时。

  显然先DP做最长上升子序列,然后做贪心。显然从前往后扫,每次扫到第一个发现长度大于要求长度,且当前值>last的就输出,然后长度--,last=当前值。这样贪心应该是正确的。

  我WA了两发,因为当长度变成0时应该及时跳出,而不是往后做。

  然后我还学了一下nlogn的最长上升子序列的DP,思想也很简单,就是从后往前做,然后维护每种长度当前的开始的结点的值最大值,对于每个i都二分查找出它之后可以接的最大长度。这显然是nlogn的。

 

  n^2 的做法:

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 10011;
21 const int inf = (1<<30);
22 int n,m,maxl;
23 int a[MAXN],f[MAXN];
24 
25 inline int getint()
26 {
27        int w=0,q=0;
28        char c=getchar();
29        while((c<'0' || c>'9') && c!='-') c=getchar();
30        if (c=='-')  q=1, c=getchar();
31        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
32        return q ? -w : w;
33 }
34 
35 inline void work(){
36     n=getint(); for(int i=1;i<=n;i++) a[i]=getint(),f[i]=1;
37     int len;
38     for(int i=n-1;i>=1;i--) {//事实上可以nlogn做最长上升子序列,记录每种长度的出现的最大的值,然后二分查找找到能够匹配的最大长度值
39     len=0; 
40     for(int j=i+1;j<=n;j++) {
41         if(a[j]>a[i] && f[j]>=len) len=f[j];
42     } 
43     f[i]=len+1; maxl=max(f[i],maxl);
44     }
45     m=getint(); int x,last;
46     for(int o=1;o<=m;o++) {//实际上这里不能直接输出,应该不断往后找可行解
47     if(o>1) printf("\n");
48     x=getint(); last=-inf;
49     if(maxl<x) { printf("Impossible"); continue; }
50     for(int i=1;i<=n;i++) {
51         if(f[i]>=x && a[i]>last) {
52         if(last!=-inf) printf(" ");
53         last=a[i]; x--;
54         printf("%d",a[i]);
55         if(!x) break;//及时跳出
56         }
57     }
58     }
59 }
60 
61 int main()
62 {
63   work();
64   return 0;
65 }

 

 

  nlogn的做法:

  

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 10011;
21 const int inf = (1<<30);
22 int n,m;
23 int a[MAXN],f[MAXN],c[MAXN];//c[i]表示长度为i的开始结点的值的最大值
24 int maxl;
25 
26 inline int getint()
27 {
28        int w=0,q=0;
29        char c=getchar();
30        while((c<'0' || c>'9') && c!='-') c=getchar();
31        if (c=='-')  q=1, c=getchar();
32        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
33        return q ? -w : w;
34 }
35 
36 inline int search(int x){//二分查找
37     int l=0,r=maxl,mid; int pos;
38     while(l<=r) {
39     mid=(l+r)>>1;
40     if(c[mid]>x) pos=mid,l=mid+1;
41     else r=mid-1;
42     }
43     return pos;
44 }
45 
46 inline void work(){
47     n=getint(); for(int i=1;i<=n;i++) a[i]=getint();
48     int now; c[0]=inf;
49     for(int i=n;i>=1;i--) {//倒着查找
50     now=search(a[i]); f[i]=now+1;
51     c[f[i]]=max(c[f[i]],a[i]);
52     maxl=max(maxl,f[i]);
53     }
54     m=getint(); int last;
55     for(int o=1;o<=m;o++) {
56     if(o!=1) printf("\n");    
57     now=getint(); last=-inf;
58     if(now>maxl) { printf("Impossible"); continue; }
59     for(int i=1;i<=n;i++){
60         if(f[i]>=now && a[i]>last) {
61         printf("%d",a[i]);
62         if(now!=1) printf(" "); else break;//记得及时退出
63         now--; last=a[i];        
64         }
65     }
66     }
67 }
68 
69 int main()
70 {
71   work();
72   return 0;
73 }

 

posted @ 2016-07-26 21:02  ljh_2000  阅读(203)  评论(0编辑  收藏  举报