1. 程式人生 > >bzoj 1046

bzoj 1046

pri tdi += put 最長 樹狀數組 spa 二分 code

一看就知道是DP了。

註意要求字典序最小,所以要從後往前做最長下降子序列。

如果不加二分或者樹狀數組之類的優化應該會TLE的吧。

輸出的時候找一下答案即可。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
int read(){
    char c; while(!isdigit(c=getchar()) && c!=-);
    int x=0,y=1; if(c==-) y=-1; else x=c-0
; while(isdigit(c=getchar())) x=x*10+c-0; return x*y; } int a[10001],f[10001],w[10001]; int find(int l,int r,int v){ while(l<=r){ int mid=l+r>>1; if(v<w[mid]) l=mid+1; else r=mid-1; } return l; } void print(int n,int l){ int pre=-2e9,fs=0;
for(int i=1;i<=n && l;i+=1) if(pre<a[i] && f[i]>=l){ if(!fs) fs=1,printf("%d",a[i]); else printf(" %d",a[i]); pre=a[i]; l--; } printf("\n"); } int main(){ int n=read(),m=0; for(int i=1;i<=n;i+=1) a[i]=read();
for(int i=n;i>=1;i-=1){ f[i]=find(1,m,a[i]); if(m<f[i]) w[++m]=a[i]; else w[f[i]]=max(w[f[i]],a[i]); } int q=read(); while(q--){ int l=read(); if(l<1 || l>m) puts("Impossible"); else print(n,l); } return 0; }

bzoj 1046