链接: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≤1000001≤n≤100000,0≤m≤10000≤m≤1000;
* 接下来输入一个长度为n的字符串S。
输出描述:
一个整数,表示题面上描述的最大价值。
示例1
输入
2
5 1
00101
2 1
01
输出
4
2
说明
第一个串翻转第三个位置,00001的价值为4;第二个串翻转第一个位置,11的价值为2。
思路
对0,1的长度求出前缀和,二分答案
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
char str[maxn];
int n, m;
int sum1[maxn], sum0[maxn];
bool check(int len)
{
for (int i = 1; i + len - 1 <= n; i++)
{
if (sum0[i + len - 1] - sum0[i - 1] <= m)
{
return true;
}
if (sum1[i + len - 1] - sum1[i - 1] <= m)
{
return true;
}
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
scanf("%s", str + 1);
sum0[0] = sum1[0] = 0;
for (int i = 1; i <= n; i++)
{
sum0[i] = sum0[i - 1];
sum1[i] = sum1[i - 1];
if (str[i] == '1')
{
sum1[i]++;
}
else
{
sum0[i]++;
}
}
int l = 0;
int r = n;
int ans = -1;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid))
{
ans = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
printf("%d\n", ans);
}
return 0;
}