Logo FiraCode 的博客

博客

CF1917C

...
FiraCode
2025-12-01 12:55:22
什么意思呢

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2023-12-25 18:21:46

思路:

首先假如数组开始全为 $0$ 怎么做。

那么显然是每进行一次操作 $1$,就立马进行操作 $2$。因为若再进行一次,那么相等的贡献最多不变,因为是对前缀加,第一次是 $1$ 满足,而第二次只有 $2$ 满足或者没有,后面同理。

然后看不全为 $0$ 怎么做。

我们发现 $n$ 比较小,考虑暴力做 $2n$ 轮,然后对于每一轮都计算贡献。也就是对于 $i(0 \le i \le 2n)$ 来说,我们就是求做 $i$ 的贡献加上剩余轮数按照刚才的策略的贡献。

而为什么做 $2n$ 轮?是因为当执行 $2n$ 轮时,你可以直接按照上述 $2$ 轮一个贡献,就可以到 $n$ 的贡献,而若一直执行的话,最多也就所有的数字都一样,最多也就是 $n$,所以没必要在往后枚举了。

当然做的轮数还要 $<d$。

时间复杂度 $\mathcal{O(Tn^2)}$。

Code:

#include <bits\/stdc++.h>

using namespace std;

int T;
int n, k, d;
int a[2010], v[100010];
int cnt[4010];

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d%d", &n, &k, &d);
		cnt[0] = 0;
		for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), cnt[0] += a[i] == i;
		for (int i = 1; i <= k; ++i) scanf("%d", &v[i]);
		for (int i = 1; i <= 2 * n && i < d; ++i) {
			cnt[i] = 0;
			for (int j = 1; j <= v[(i - 1) % k + 1]; ++j) a[j]++;
			for (int j = 1; j <= n; ++j) cnt[i] += a[j] == j;
		}
		int ans = 0;
		for (int i = 0; i <= 2 * n && i < d; ++i) {
			\/\/ cout << cnt[i] << endl;
			ans = max(ans, cnt[i] + (d - i - 1) \/ 2);
		}
		printf("%d\n", ans);
	}
	return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。