zoukankan      html  css  js  c++  java
  • CF933A 题解

    Luogu-CF933A

    题目分析

    这题乍一看不好想,但是看到 \(1 \leq a_i \leq 2\) 时,便发现有玄机。

    可得知最终答案是在 \([1,1,1,...][2,2,2,...][1,1,1,...][2,2,2,...]\) 这样的序列中,通过翻转第 \(2\)\(3\) 个序列之后得出。

    我们可以用动态规划来维护每一段的最大值。

    定义 \(f[i][j]\) 为前 \(i\) 个数中前 \(j\) 段的答案。

    对于序列

    \(111112222\)

    可以将其按上面分成两组。

    合理运用一下判等,

    则有

    \[f[i][1]=f[i-1][j]+(a[i]==1) \]

    \[f[i][2]=max(f[i−1][1],f[i−1][2]+(a[i]==2)) \]

    对于序列

    \(12212211212\)

    得到最终答案时的最长不下降子序列是:

    \(111122222\)

    在此基础上翻转回去,则为:

    \(122221112\)

    发现它符合上面的按 \(4\) 个组的分组形式。

    则有

    \[f[i][3]=max(f[i−1][2],f[i−1][3]+(a[i]==1) \]

    \[f[i][4]=max(f[i−1][3],f[i−1][4]+(a[i]==2) \]

    观察,发现状态转移方程可以压掉第一维。

    核心代码

    ll n,ans,f[12];
    int main()
    {
        n=read();
        for (ll i = 1; i <= n; i++)
        {
            ll tmp;
            scanf("%lld", &tmp);
            f[1] += (tmp == 1);
            f[2] = max(f[1], f[2] + (tmp == 2));
            f[3] = max(f[2], f[3] + (tmp == 1));
            f[4] = max(f[3], f[4] + (tmp == 2));
        }
        printf("%lld\n",f[4]);
        return 0;
    }
    
  • 相关阅读:
    Codeforces Round #326 (Div. 2)
    UVAlive 6611 Alice's Print Service 二分
    codeforces868D Huge Strings
    [HNOI2016]大数
    [NOI 2015]软件包管理器
    幻方
    poj3728 商务旅行
    [SCOI2016]背单词
    [USACO12FEB]牛的IDCow IDs
    [Cqoi2010]扑克牌
  • 原文地址:https://www.cnblogs.com/EdisonBa/p/14702135.html
Copyright © 2011-2022 走看看