【bzoj1046】 HAOI2007—上升序列
http://www.lydsy.com/JudgeOnline/problem.php?id=1046 (题目链接)
题意
给出一个数列,求数列中长度为L的下标字典序最小的上升子序列。
Solution
将数列倒过来求一遍不上升子序列,记录下以当前数为结尾的最长不上升序列的长度,也就是记录下了原数列中以当前数为开头的最长上升序列的长度。这样就很好处理了。
代码
// bzoj1046 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; inline LL getint() { int f,x=0;char ch=getchar(); while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=10010; int f[maxn],g[maxn],a[maxn]; int n,q; int find(int x) { int l=1,r=n,res=0; while (l<=r) { int mid=(l+r)>>1; if (g[mid]>x) l=mid+1,res=mid; else r=mid-1; } return res; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=n;i>=1;i--) { int x=find(a[i]); f[i]=x+1; g[f[i]]=max(g[f[i]],a[i]); } scanf("%d",&q); while (q--) { int x;scanf("%d",&x); int flag=0,p=0; for (int i=1;i<=n;i++) { if (f[i]>=x && a[i]>a[p]) { flag=1; x--; if (x==0) printf("%d",a[i]); else printf("%d ",a[i]); p=i; } if (x==0) break; } if (!flag) printf("Impossible"); printf("\n"); } return 0; }
This passage is made by MashiroSky.