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