C. Hard Process CodeForces - 660C

原题链接 位于CodeForcesicon-default.png?t=M1L8https://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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值