链接:https://ac.nowcoder.com/acm/contest/893/F
来源:牛客网
题目描述
你有一个长度为 n 的 01 串S,你可以执行最多 m 次操作。
对于每次操作,你可以选择一个位置 i 满足 1≤i≤n,翻转这一位的值,0变成1,1变成0。
定义一个 01 串的价值为其中最长连续0的个数和最长连续1的个数的较大值,求S在经过最多m次操作后的最大价值。
输入描述:
* 第一行一个整数 T ,表示接下来有 T 个样例。
* 首先输入n,m,表示S串的长度n和操作次数m,其中1≤n≤100000,0≤m≤1000;
* 接下来输入一个长度为n的字符串S。
输出描述:
一个整数,表示题面上描述的最大价值。
示例1
输入
2
5 1
00101
2 1
01
输出
4
2
说明
第一个串翻转第三个位置,00001的价值为4;第二个串翻转第一个位置,11的价值为2。
思路:这里的想法就是 尺取
sovle1 ()是只要遇到了 1 就记下来,这个要翻转一次,只要 翻转的次数 count 没有超过 m 就继续向右走,当 翻转的次数超过了m ,就得操作左边的了, 当左边是 1 的话,count -- 意味着这一个不翻转了,还让他是 1 ,这样一直走下去,num记录最大的翻转区间
sovle2 ()与sovle1()类似,只不过是 看到 0 就翻转
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<cmath>
const int maxn=1e5+5;
typedef long long ll;
using namespace std;
int n,m;
string s;
int sovle1(){//把是 1 的翻转
int l=0,r=0,count=0,num=0;
while(r<n){
if(s[r]=='1')
count++;
while(count>m){
if(s[l]=='1')
count--;
l++;
}
num=max(num,r-l+1);
r++;
}
return num;
}
int sovle2(){//把是 0 的翻转
int l=0,r=0,count=0,num=0;
while(r<n){
if(s[r]=='0')
count++;
while(count>m){
if(s[l]=='0')
count--;
l++;
}
num=max(num,r-l+1);
r++;
}
return num;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
cin>>s;
int ans=max(sovle1(),sovle2());
printf("%d\n",ans);
}
return 0;
}