nlogn的做法就是记录了在这之前每个长度的序列的最后一项的位置,这个位置是该长度下最后一个数最小的位置。显然能够达到最优。
BZOJ 1046中里要按照字典序输出序列,按照坐标的字典序,那么我萌可以把序列先倒着做最长下降子序列,然后我萌就可以知道以a[i]为开头的最长的长度了。每次扫一遍记录答案即可.
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 7 inline void Get_Int(int &x) 8 { 9 char ch=getchar(); x=0; 10 while (ch<'0' || ch>'9') ch=getchar(); 11 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 12 } 13 const int Maxn=100100; 14 const int Inf=0x3f3f3f3f; 15 int n,m,a[Maxn],F[Maxn],Pos[Maxn],B[Maxn],top,Ans,x; 16 inline int Max(int x,int y) {return x>y?x:y;} 17 inline int Find(int x) 18 { 19 int l=1,r=n,Ret=0; 20 while (l<=r) 21 { 22 int mid=(l+r)>>1; 23 if (a[Pos[mid]]>x) Ret=mid,l=mid+1; else r=mid-1; 24 } 25 return Ret; 26 } 27 int main() 28 { 29 Get_Int(n); 30 for (int i=1;i<=n;i++) Get_Int(a[n-i+1]); 31 F[1]=1; Pos[1]=1; int Ans=1; 32 for (int i=2;i<=n;i++) 33 { 34 int t=Find(a[i]); 35 Pos[t+1]=i; 36 F[i]=t+1; 37 Ans=Max(t+1,Ans); 38 } 39 40 Get_Int(m); 41 for (int i=1;i<=m;i++) 42 { 43 Get_Int(x); int top=0,Now=-Inf; 44 if (Ans<x) {puts("Impossible"); continue;} 45 for (int i=n,j=x;i&&j;i--) 46 if (F[i]>=j && Now<a[i]) 47 { 48 Now=a[i]; 49 B[++top]=a[i]; 50 j--; 51 } 52 for (int i=1;i<x;i++) printf("%d ",B[i]); printf("%d\n",B[x]); 53 } 54 return 0; 55 }