码迷,mamicode.com
首页 > 其他好文 > 详细

CF933A 题解

时间:2021-05-20 17:52:49      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:cpp   答案   翻转   分组   最大值   isp   printf   ==   span   

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;
}

CF933A 题解

标签:cpp   答案   翻转   分组   最大值   isp   printf   ==   span   

原文地址:https://www.cnblogs.com/EdisonBa/p/14702135.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!