原题链接 位于CodeForceshttps://codeforces.com/problemset/problem/660/C
翻译
ff 有一个长为 n的数组 a,并且数组 a 中的元素只有 0 和 1。
我们定义这样的 01 数组的价值为其中最长的连续 1 的的长度。ff 为了增加手中数组的价值,学习了把 0 变成 1 的魔法,最多可以释放 k 次。
现在他想知道,这个数组的价值最大能够变成多少?
题意与思路
也就是我们需要找到最长的区间,其中 0 的个数不超过 k。
我采用从右向左枚举,每次枚举用 二分法 找到最长合法区间的左边界并与记录的最大值作比较维护最大值,最终输出。
代码
#include <bits/stdc++.h>
using namespace std;
int num[300100];
int num0[300100];
int n, k;
int foundL(int r)
{
int l = 1, R = r;
int mid;
while (l <= r)
{
mid = (l+r)/2;
if (num0[R] - num0[mid-1] <= k) r = mid-1;
else l = mid+1;
}
return l;
}
/*
l
m
r
R
1 0 0 1 1 0 1
0 0 1 2 2 2 3 3*/
int main()
{ start:
int i, j, t;
scanf("%d%d", &n, &k);
num0[0] = 0;
for (i = 1; i <= n; i++)
{
num0[i] = num0[i-1];
scanf("%d", &num[i]);
if (!num[i]) num0[i]++;
}
/*for (i = 0; i <= n; i++)
printf ("%d ", num0[i]);
printf ("\n");*/ //输出num0数组
int nmax = 0;
int l = 1, r = 0; // 符合条件的最大左右边界
for (i = n; i >= 1; i--)
{
t = foundL(i); // 符合条件的左边界
if (i-t+1 > nmax)
{
l = t;
r = i;
nmax = r-l+1;
//printf ("l%d r%d max%d\n", l, r, nmax);
}
}
printf ("%d\n", nmax);
for (i = l; i <= r; i++)
num[i] = 1;
for (i = 1; i <= n; i++)
printf ("%d ", num[i]);
//goto start; // 无限测试
return 0;
}