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 }