当前位置: 代码迷 >> 综合 >> Black White (尺取法)
  详细解决方案

Black White (尺取法)

热度:52   发布时间:2023-11-22 13:41:41.0

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