AtCoder Beginner Contest 408-d

原题链接

方法一

看到这道题,我们考虑将一段区间内的0都变成1,区间外的1都变成0,那么此时的操作次数为区间内0的个数加上区间外1的个数,转换为整个序列1的个数加上区间内0的个数减去1的个数,而整个序列1的个数为一个常量,所以我们只要找到一个区间使得区间内0的个数减去1的个数最小,并将这个值加上整个序列1的个数,便是最终的答案。现在我们考虑如何找到一个区间使得区间内0的个数减去1的个数最小,运用前缀和的思想,维护一个数组\(a\)来表示1到当前位置中0的个数减去1的个数,则根据贪心,每当遍历到一个\(a_i\),用一个变量\(x\)来维护1到\(i\)\(a_i\)的最大值,并用\(a_i\)减去\(x\),得到的便是以\(i\)为结尾的区间中0的个数减1的个数的最小值,再用一个变量\(y\)来维护这个最小值,则最终答案为整个序列1的个数加上\(y\)

CODE

#include<bits/stdc++.h>
using namespace std;
int t,n,a[200010],sum[200010];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		char c;
		int tp;
		for(int i=1;i<=n;i++)
		{
			cin>>c;
			tp=c-'0';
			a[i]=a[i-1]+tp;
			sum[i]= i-2*a[i];
		}
		int maxn=0,minn=0x7f7f7f7f;
		for(int i=1;i<=n;i++)
		{
			maxn=max(maxn,sum[i]);
			minn=min(minn,sum[i]-maxn);
		}
		cout<<minn+a[n]<<endl;
	}
	return 0;
}
posted @ 2025-06-01 09:51  CMY2013  阅读(28)  评论(0)    收藏  举报