CF1082E 增加中的频率

1 CF1082E 增加中的频率

2 题目描述

给出一个长度为 \(n\) 的数组 \(a\)。你可以选择一段 \([𝑙,𝑟](1≤𝑙≤𝑟≤𝑛)\) 和整数值 \(𝑘\) (正、负或者零都可以)并将区间内的每个数都加 \(k\)
在一次这样的操作后,可以获得的具有值𝑐的元素的最大可能数目是多少?

3 题解

我们发现,每个数具体加上几变成 \(c\) 对答案并没有影响,所以我们可以省略这一过程,只用找到相等的数即可。我们可以把所有数分成两类,一类是等于 \(c\) 的数,一类是不等于 \(c\) 的数。这时,我们就可以用 \(dp\) 解决这道题目了。设状态 \(dp_i\) 表示当前遍历到的等于 \(i\) 的数之前通过增加得到的等于 \(c\) 的最大个数。转移方程就是:\(dp_{a_i} = max(dp_{a_i}+1, sum_{i-1} + 1)\)。具体意思就是,在上一个等于 \(a_i\) 的数的基础上取将这个数和上一相等的数之间全部增加 \(c - a_i\) 和完全不增加两种情况中得到的 \(c\) 的个数最多的个数。最终将所有的值取 \(max\) 即可。

4 代码(空格警告):

#include <iostream>
using namespace std;
const int N = 5e5+10;
int n, c, ans;
int a[N], sum[N], f[N];
int main()
{
    cin >> n >> c;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (a[i] == c) sum[i] = sum[i-1]+1;
        else sum[i] = sum[i-1];
    }
    for (int i = 1; i <= n; i++)
    {
        f[a[i]] = max(f[a[i]]+1, sum[i-1]+1);
        ans = max(ans, f[a[i]] + sum[n] - sum[i]);
    }
    cout << ans;
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-02-05 16:07  David24  阅读(43)  评论(0编辑  收藏  举报