Black & White (尺取法)

版权声明:转载请注明出处 https://blog.csdn.net/qq_37708702/article/details/90050244

题目链接
题目描述
你有一个长度为 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;
}

猜你喜欢

转载自blog.csdn.net/qq_37708702/article/details/90050244