题意: 给出一个01串(len<=1e5), 每次操作可以把1个0换成1或者把1换成0, 最多可进行m次操作, 问最多能有多少个连续的1或者0.
思路: 二分答案, 如果能得到x个连续的1或0, 那么就看x能否再大一点; 如果不能得到x个连续的1或0, 就看x小一点行不行.
对于每个x, 检查每个长度是x的区间改成全1或全0的代价是否<=m即可.
代码:
#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;
const int M=2e5+5;
const int inf=1e9+5;
const int mod=1e9+7;
//memset(a,0x3f,sizeof(a));
int _,n,m;
char a[M];
int sum0[M];
int sum1[M];
int main() {
scanf("%d",&_);
while(_--) {
scanf("%d%d",&n,&m);
scanf("%s",(a+1));
sum0[0]=0;
sum1[0]=0;
for(int i=1; i<=n; i++) {
sum0[i]=sum0[i-1]+(a[i]=='0'?1:0);
sum1[i]=sum1[i-1]+(a[i]=='1'?1:0);
}
int l=1;
int r=n;
int ans=1;
while(l<=r) {
int mid=(l+r)/2;
int now=inf;
for(int i=1; i+mid-1<=n; i++) {
now=min(now,sum0[i+mid-1]-sum0[i-1]);//区间内0的个数,即为改成全1的代价
now=min(now,sum1[i+mid-1]-sum1[i-1]);//区间内1的个数,即为改成全0的代价
}
if(now<=m) {
l=mid+1;
ans=mid;
}
else
r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}