【bzoj1046】 HAOI2007—上升序列

http://www.lydsy.com/JudgeOnline/problem.php?id=1046 (题目链接)

题意:给出一个数列,求数列中长度为L的下标字典序最小的上升子序列。

Solution
  将数列倒过来求一遍不上升子序列,记录下以当前数为结尾的最长不上升序列的长度,也就是记录下了原数列中以当前数为开头的最长上升序列的长度。这样就很好处理了。

代码:

// bzoj1046
#include
#include
#include
#include
#include
#include
#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;
}

你可能感兴趣的:(bzoj,递推与动规)