题目链接
题目描述
你有一个长度为 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()同理,只不过见到’0’就反转
尺取法视频
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int t,n,m,a[N];
int solve1(){
// 把'1'反转int l = 1,r = 1,cnt = 0,num = -1;while(l <= r && r <= n){
if(a[r] == 1) cnt++;while(cnt > m){
if(a[l] == 1) cnt--;l++;}num = max(num,r - l + 1);r++;}return num;
}
int solve2(){
// 把'0'反转int l = 1,r = 1,cnt = 0,num = -1;while(l <= r && r <= n){
if(a[r] == 0) cnt++;while(cnt > m){
if(a[l] == 0) cnt--;l++;}num = max(num,r - l + 1);r++;}return num;
}
int main(){
scanf("%d",&t);while(t--){
scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++) scanf("%1d",a + i);printf("%d\n",max(solve1(),solve2()));}return 0;
}