题解:
神TM的字典序最小。。。。。。这题的字典序最小是位置的字典序最小。。。仔细读读题目
所以。我们求出以每个点为起点的最长递增子序列。。然后输出的话。贪心就行
如何求每个点为起点的最长递增子序列
回忆一下LIS的o(nlog(n))算法
我们逆向求最长递减子序列即可.
代码:
#include<bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define se second #define fs first #define ll long long #define CLR(x) memset(x,0,sizeof x) #define MC(x,y) memcpy(x,y,sizeof(x)) #define SZ(x) ((int)(x).size()) #define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define INF 2097152 typedef pair<int,int> P; const double eps=1e-9; const int maxn=10010; const int mod=10007; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } //----------------------------------------------------------------------------- int a[maxn],b[maxn],c[maxn],f[maxn]; int bs(int m,int l,int r)//大于m的最小数 { int L,R,Mid,Goal; L=1,R=r+1; while(L<=R) { Mid=(L+R)>>1; if(c[Mid]>m) { Goal=Mid; L=Mid+1; } else R=Mid-1; } return Goal; } int main() { int n,m,p; n=read(); for(int i=1;i<=n;i++) { a[i]=read(); b[n+1-i]=a[i]; } int tmp=1; c[tmp]=b[1]; f[n]=1; for(int i=2;i<=n;i++) { if(b[i]<c[tmp]) { c[++tmp]=b[i]; f[n+1-i]=tmp; } else { int pos=bs(b[i],1,tmp); f[n+1-i]=pos+1; if(c[pos+1]<b[i]) c[pos+1]=b[i]; } } m=read(); a[0]=-INF; int pos; for(int i=1;i<=m;i++) { p=read(); if(p>tmp) printf("Impossible\n"); else { pos=0; for(int i=1;i<=n;i++) { if(!p) break; if(f[i]>=p&&a[i]>a[pos]) { if(p>1) printf("%d ",a[i]); else printf("%d\n",a[i]); p--; pos=i; } } } } return 0; }
时间: 2024-10-25 00:38:06