bzoj1046 [HAOI2007]上升序列

题目链接

二分优化LIS

字典序最小的方案不好求。

于是就倒过来求以一个数开头的最长上升子序列。

字典序小的放前面。

输出时取最优就好。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<string>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<ctime>
 9 #include<queue>
10 #include<map>
11 #include<set>
12 using namespace std;
13 const int INF=2147483647;
14 int n,f[10010],a[10010],stack[10010],top,temp,m,x;
15 int main()
16 {
17     scanf("%d",&n);
18     memset(stack,128,sizeof(stack));
19     stack[top]=INF;
20     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
21     for(int i=n;i>=1;i--)
22     {
23         int l=0,r=top,ans=0;
24         while (l<=r)
25         {
26           int m=(l+r)>>1;
27           if (a[i]<stack[m])ans=m,l=m+1;
28           else r=m-1;
29         }
30         f[i]=ans+1;top=max(top,f[i]);
31         stack[f[i]]=max(stack[f[i]],a[i]);    
32     }
33     scanf("%d",&m);
34     for(int i=1;i<=m;i++)
35     {
36         scanf("%d",&x);
37         if(x>top)cout<<"Impossible\n";
38         else if(!x)cout<<"\n";
39         else for(int i=1,t=-INF;i<=n;i++) 
40               if(f[i]>=x&&t<a[i]) 
41               {
42                 printf("%d",a[i]),x--,t=a[i];
43                 if(x)printf(" ");
44                 else {cout<<"\n";break;}
45               }    
46     }
47     return 0;
48 }

 

posted @ 2016-01-22 15:03  HugeGun  阅读(120)  评论(0编辑  收藏  举报