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