• 单调序列 解题报告


    单调序列

    ( t{GISPZJZ}) 有一个长度为 (n) 的序列 (a_1,a_2,dots,a_n)。 序列的所有元素都是 (1) 或者 (2)
    我们称一序列是该序列的不下降子序列 (p_1,p_2,dots,p_k), 满足 (1le p_1<p_2<p_3<dots <p_kle n), 且(a_{p_1}le a_{p_2}le dots le a_{p_n})
    现在 ( t{GISPZJZ}) 可以选择序列中的一段区间([L,R]), 然后将整段反转, 例如挑选区间([2,4]),可以将序列((a_1,a_2,a_3,a_4,a_5))变换为((a_1,a_4,a_3,a_2,a_5))。 在此基础上, ( t{GISPZJZ}) 希望在反转后, 序列的最长不下降子序列最长。 当然, ( t{GISPZJZ}) 也可以选择不反转任何区间。 现在要求出最优情况下, 序列的最长不下降子序列的长度。

    输入:

    第一行一个正整数 (n)
    第二行 (n) 个数, 分别为 (a_1,a_2,dots,a_n), 满足 (1le a_ile 2)

    输出:

    一行一个正整数 (x), 表示答案。

    数据范围:

    对于(10\%)的数据, (1le nle 10)
    对于(40\%)的数据, (1le nle 200)
    对于(70\%)的数据, (1le n le 2000)
    对于(100\%)的数据, (1le nle 100000)


    思路还是很巧妙的。

    最开始想把一串的缩在一起做,发现讨论起来非常麻烦。

    观察了一下发现翻转后不就是把(000111)什么的变成了可以选(000111000111)这样类似的了吗?

    于是直接划分一下状态( t{DP})即可,是一个非常好的思路啊。


    Code:

    #include <cstdio>
    const int N=1e5+10;
    int a[N],dp[N][4],n,ans;
    int max(int x,int y){return x>y?x:y;}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",a+i),--a[i];
        for(int i=1;i<=n;i++)
        {
            dp[i][0]=dp[i-1][0]+(a[i]==0);
            dp[i][1]=max(dp[i-1][0],dp[i-1][1])+(a[i]==1);
            dp[i][2]=max(dp[i-1][1],dp[i-1][2])+(a[i]==0);
            dp[i][3]=max(dp[i-1][2],dp[i-1][3])+(a[i]==1);
            ans=max(max(dp[i][0],dp[i][1]),max(dp[i][2],dp[i][3]));
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    2017.11.2

  • 相关阅读:
    3.5 操作系统习题
    04_jni开发常见错误_本地方法没有找到
    3.4 目录和spooling
    3.3 作业管理
    03_jni_helloworld_完成
    ASP.NET MVC 4 过滤器(Authorize)
    MVC实现实现文件流打包成压缩包
    MVC实现实现文件流打包成压缩包
    MVC实现实现文件流打包成压缩包
    图解分布式架构的演进过程!
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9896022.html
Copyright © 2020-2023  润新知