P9540 题解

题目传送门

思路

刚看到这题,无从下手,怎么办?看看部分分。但是写部分分却对想到正解有作用。

首先,我们看看特殊性质 A。所有数字都 =y=y 或所有数字都 y\ne y,那现在翻转操作是没用的,但题目要求我们要必须刚好操作 zz 次,所以我们只要随便翻转一下,把这 zz 次浪费掉即可。我们对所有数字都 =y=y 的情况不用操作,输出 00,而对所有数字都 y\ne y 的情况统一做一次变换操作即可,输出 11

我们再看看 z>nz>n 的情况。对于每次翻转,我们可以把两块连续y\ne y 的部分合并到一起。如果 z>nz>n,那么所有 y\ne y 的数字将会被合到一起,这样我们只要看是不是所有数字都是 yy 即可,如果是的,那输出 00,否则输出 11

z=0z=0 时,这时候我们要考虑合并了。要使合并最优,当然是把所有 =y=y 的数字尽可能放一起,所有 y\ne y 的数字尽可能放一起。只有变换操作,那我们只要把所有 y\ne y 的连续数字块一起变换即可,所以我们只要统计 y\ne y 的连续块个数就好了。

最后,部分分都想完了,正解也就出来了。因为每次翻转操作会把两块 y\ne y 的连续块连一起,连续块个数也就减少了 11,所以正解只要在 z=0z=0 的方法的基础上,把 y\ne y 的连续块个数减掉 zz 就好了。需要注意的是,如果把 y\ne y 的连续块个数减掉 zz 后答案不足 11 了,那这个问题就转化成了 z>nz>n 的情况,所以要把答案和 11max\max。还有,当所有数都是 yy 的时候,我们不需要操作,所以只要输出 00 就可以了,这个特判一下就好了。

代码

# include <bits/stdc++.h>
using namespace std;
int n, y, z, a[2000005], ans, ans2;
bool f = 1; //记录是否有 != y 的元素
int main () {
	cin >> n >> y >> z;
	for (int i = 0; i < n; ++ i)
		cin >> a[i];
	for (int i = 0; i < n; ++ i)
		cin >> a[i + n];
	for (int i = 0; i < n << 1; ++ i)
		if (a[i] != y) {
			f = 0;
			break ;
		}
	if (f) { //特判
		cout << 0;
		return 0;
	}
	for (int i = 1; i < n; ++ i)
		if (a[i] == y && a[i - 1] != y) //算连续块
			++ ans;
	if (a[n - 1] != y) //最后一个块别忘记
		++ ans;
	for (int i = n + 1; i < n << 1; ++ i)
		if (a[i] == y && a[i - 1] != y)
			++ ans2;
	if (a[n * 2 - 1] != y)
		++ ans2;
	cout << max (1, max (ans, ans2) - z); //取个 max
	return 0;
}
posted @ 2023-08-15 22:35  Vitamin_B  阅读(10)  评论(0)    收藏  举报  来源