• 凤凰院凶真 解题报告


    凤凰院凶真

    Description

    (α) 世界线.

    凤凰院凶真创立了反抗 (SERN) 统治的组织 “瓦尔基里”. 为了脱离 (α) 线, 他需要制作一个世界线
    变动率测量仪.

    测量一个世界线相对于另一个世界线的变动率, 实质上就是要求出这两个世界线的最长公共合
    法事件序列.

    一个世界线的事件逻辑序列是一个正整数序列, 第 (k) 个数表示第 (k) 个事件发生的时间.

    对于一个世界线, 一个合法的事件序列是事件逻辑序列的一个子序列, 满足时间严格递增.

    现在, 对于两个不同的世间线 (α) ,(β), 求出最长的一个事件序列, 满足这个序列在 (α,β) 世界线中
    均是合法的.

    这个序列也就是之前提到过的最长公共合法事件序列

    Input Format

    第一行一个整数 (n), 表示 (α) 世界线的事件个数.
    第二行 (n) 个整数 (a_1,a2,dots,a_n), 表示 (α) 世界线的事件逻辑序列.
    第三行一个整数 (m), 表示 (β) 世界线的事件个数.
    第四行 (m) 个整数 (b_1,b_2,dots,b_m), 表示 (β) 世界线的事件逻辑序列.

    Output Format

    第一行一个整数 (k), 表示最长公共合法事件序列的长度.
    第二行 (k) 个整数, 表示最长公共合法事件序列. 如果有多解, 输出任意一个.

    Constraints

    无论执迷过去
    还是叹息未来
    皆是不准有丝毫误算的必然

    子任务编号 分数 (n,m) (a_i,b_i)
    1 10 (le 10) (le 2^{30})
    2 10 (le 20) (le 2^{30})
    3 10 (le 100) (le 2^{30})
    4 15 (le 400) (le 2^{30})
    5 15 (le 1000) (le 200)
    6 15 (le 1000) (le 2^{30})
    7 25 (le 5000) (le 2^{30})

    对于(100\%)的数据,(1 le n,m le 5000,1 le a_i,b_i le 2^{30})

    Solution

    就是(LCIS)问题啦,其实还是比较巧妙的感觉

    (dp_{i,j})代表(a)串前(i)个位置与(b)串前(j)个位置匹配并且(j)为匹配的末尾的最长长度。

    朴素的,有

    (a_i=b_j),则(dp_{i,j}=maxlimits_{b_k<a_i} dp_{i-1,k}+1)

    否则,(dp_{i,j}=dp_{i-1,j})

    发现(k)那一维是不需要枚举的,直接用前缀最大值优化一下就可以了,因为在(i)一定时,决策集合是递增的。


    Code:

    #include <cstdio>
    const int N=510;
    int dp[N][N],pre[N][N],ans[N],tot,n,m,a[N],b[N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        scanf("%d",&m);
        for(int i=1;i<=m;i++) scanf("%d",b+i);
        for(int i=1;i<=n;i++)
        {
            int mx=0,id=0;
            for(int j=1;j<=m;j++)
            {
                if(a[i]==b[j])
                    dp[i][j]=mx+1,pre[i][j]=id;
                else
                    dp[i][j]=dp[i-1][j];
                if(dp[i-1][j]>mx&&a[i]>b[j]) mx=dp[i-1][j],id=j;
            }
        }
        int mx=0,r1=n,r2;
        for(int i=1;i<=m;i++)
            if(mx<dp[n][i])
                mx=dp[n][i],r2=i;
        ans[++tot]=r2;
        printf("%d
    ",mx);
        if(mx==0) return 0;
        while(r1&&r2)
        {
            if(pre[r1][r2])
            {
                r2=pre[r1][r2];
                ans[++tot]=r2;
            }
            else
                --r1;
        }
        for(int i=tot;i;i--)
            printf("%d ",b[ans[i]]);
        return 0;
    }
    
    

    2018.10.19

  • 相关阅读:
    shell 实现word count
    jvm 参数调优
    Java注解处理器(转)
    JVM -XX: 参数介绍(转)
    如何在Linux下重命名多个文件
    Kafka学习之broker配置(0.8.1版)(转)
    linux 历史命令用法(转)
    hive-site.xml 参数设置
    Hadoop-2.2.0 + Hbase-0.96.2 + Hive-0.13.1(转)
    正则表达式通过Unicode属性匹配
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9817488.html
Copyright © 2020-2023  润新知