zoukankan      html  css  js  c++  java
  • bzoj1046: [HAOI2007]上升序列

    首先是O(nlogn) 的最长上升子序列,我居然一直不会。。。。(雾)。

    用一个maxv[i] 数组表示长度为i的上升子序列的第一个数的最大值,这样就可以二分求当前上升子序列的长度了。

    注意这道题字典序最小是指下标。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 10000 + 10;
    const int INF = 0x3f3f3f3f;
    int a[maxn],maxv[maxn],f[maxn],res[maxn];
    int n,m,maxlen; 
    
    void input() {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
    }
    
    void build() {
        for(int i = 1; i <= n; i++) maxv[i] = -INF;
        maxv[0] = INF; 
        maxv[1] = a[n];
        f[n] = 1;
        maxlen = 1;
        for(int i = n-1,cur,l,r,mid; i >= 1; i--) {
            l = 0; r = maxlen+1; cur = 0;
            while(l <= r) {
                mid = (l+r) >> 1;
                if(a[i] < maxv[mid]) l=cur= mid + 1;
                else r = mid - 1;
            }
            maxlen = max(maxlen,f[i] = cur);
            maxv[cur] = max(maxv[cur],a[i]);
        }
    }
    
    void solve() {
        scanf("%d",&m);
        while(m--) {
            int len,cnt;
            scanf("%d",&len);
            if(len > maxlen) {
                printf("Impossible
    ");
                continue;
            }
            res[cnt=0] = -INF;
            for(int i = 1; i <=n && cnt < len; i++)
                if(f[i] >= len-cnt && a[i] > res[cnt]) 
                    res[++cnt] = a[i];
            for(int i = 1; i < cnt; i++) printf("%d ",res[i]);
            printf("%d
    ",res[cnt]);
        }
    }
    
    
    int main() {
        input();
        build();
        solve();
        return 0;
    }
  • 相关阅读:
    Json的序列化与反序列化
    RelativeSource设定绑定方向
    Java导出Excel工具类
    CentOS配置ssh免密码登录
    CentOS为用户增加root权限
    CentOS安装RabbitMQ步骤
    CentOS配置主机名和主机映射
    CentOS配置静态IP
    Java执行系统命令工具类(JDK自带功能)
    Linux定时任务
  • 原文地址:https://www.cnblogs.com/invoid/p/5375523.html
Copyright © 2011-2022 走看看