Enduring Exodus (CodeForces - 655C)三分法 (连续k+1个位置,距离中间最短的距离)

                                                          Enduring Exodus

                                                                              time limit per test 2 seconds

                                                                      memory limit per test 256 megabytes

                                                                                   input standard input

                                                                                 output standard output

In an attempt to escape the Mischievous Mess Makers' antics, Farmer John has abandoned his farm and is traveling to the other side of Bovinia. During the journey, he and his k cows have decided to stay at the luxurious Grand Moo-dapest Hotel. The hotel consists of nrooms located in a row, some of which are occupied.

Farmer John wants to book a set of k + 1 currently unoccupied rooms for him and his cows. He wants his cows to stay as safe as possible, so he wishes to minimize the maximum distance from his room to the room of his cow. The distance between rooms i and j is defined as |j - i|. Help Farmer John protect his cows by calculating this minimum possible distance.

Input

The first line of the input contains two integers n and k (1 ≤ k < n ≤ 100 000) — the number of rooms in the hotel and the number of cows travelling with Farmer John.

The second line contains a string of length n describing the rooms. The i-th character of the string will be '0' if the i-th room is free, and '1' if the i-th room is occupied. It is guaranteed that at least k + 1 characters of this string are '0', so there exists at least one possible choice of k + 1 rooms for Farmer John and his cows to stay in.

Output

Print the minimum possible distance between Farmer John's room and his farthest cow.

Examples

input

7 2
0100100

output

2

input

5 1
01010

output

2

input

3 2
000

output

1

Note

In the first sample, Farmer John can book room 3 for himself, and rooms 1 and 4 for his cows. The distance to the farthest cow is 2. Note that it is impossible to make this distance 1, as there is no block of three consecutive unoccupied rooms.

In the second sample, Farmer John can book room 1 for himself and room 3 for his single cow. The distance between him and his cow is 2.

In the third sample, Farmer John books all three available rooms, taking the middle room for himself so that both cows are next to him. His distance from the farthest cow is 1.

题解

题的大意是:有年春暖花开时,小明(假装他长大当了老师)带着他的k个同学出去郊游,这景色太美了呀,就舍不得回家了,于是小明就找了一家和风旅馆,准备住下。老板告诉小明,一些房间已经有人预定了,小明和同学们可能不能全都挨在一起住。没办法呀,谁叫这家旅馆风景好呢,小明就准备在这n间房中找k+1间(毕竟小明不是米迦尔,也是要睡觉的)住下,但是为了小盆友们的安全,必须让小盆友们离着老师最近。现在老板给出这n间房的使用情况(0表示没有人,1表示有人),呐,现在大家该怎么住才能保证最安全呢?就要我们算出保证小盆友们最安全的情况下,离小明最远的小盆友与小明的距离。(1 ≤ k < n ≤ 100 000) 

这道题首先把所有空房间找出来,编号从小到大放到数组里,然后从头开始,取k+1个房间,在这k+1个房间里找到题中要求的数据,再取下k+1个房间,数据取最佳即可。

那么,在这k+1个房间里怎么求最短距离呢?分析一下不难知道,小明应该是住在中间左右的位置的,最佳位置所得的距离一定的是最短的,向某一边移动,那么距离另一边的距离会越来越大,距离画出来就类似于二次函数(类似!),暴力肯定是会超时的,要降低时间复杂度的话,就需要用到三分法。

 

二分是在有序序列找某值,而三分是在类似二次函数图像上找最值。

下面以开口向上的图为例简述一下三分算法:

先取两端的两个点 l,r。

取中点mid = (l + r) >> 1。

再取 mid 和 r的中点(或 l 和 mid的中点)mmid = (mid + r ) >> 1。

下图以取 mid 和 r的中点为例

由图易知,

当 l < r-1(也就是端点中间还有点)时

因为 mid < mmid

①f(mid)<f(mmid)时,mmid一定在极点右侧,可令 r = mmid缩小范围

②f(mid)>f(mmid)时,mid一定在极点左侧,可令 l = mid缩小范围

当 l == r-1 时,极点就是 l 或 r

此时比较 f(l) 和 f(r) 即可,小的就是极点

 

开口向上和取 l 和 mid 的中点的情况也可以用相同证法得出结论,这里我就不说了

下面代码与题目n,k值相反

# include <cstdio>
# include <algorithm>

using namespace std;
const int maxn = 100000 + 10;
int b[maxn];

int san(int l, int r)
{
	int n = l, m = r;
	while(l<r-1)
	{
		int mid = (r+l)>>1;
		int mmid = (r+mid)>>1;
		
		int fm = max(b[mid]-b[n],b[m]-b[mid]);
		int fmm = max(b[mmid]-b[n],b[m]-b[mmid]);
		
		if(fm>fmm) l = mid;
		
		else r = mmid;
	}
	int fm = max(b[l]-b[n],b[m]-b[l]);
	int fmm = max(b[r]-b[n],b[m]-b[r]);
	return min(fm,fmm);
 } 

int main() 
{
	int k, n;
	scanf("%d%d",&k,&n);
	int mark = 0; 
	char s[maxn];
	scanf("%s",s);
	for(int i=0;i<n;i++) if(!(s[i]-'0')) b[mark++] = i;
	
	int ans = maxn;
	for(int i=0;i<mark-k;i++) ans = min(ans,san(i,i+k));
	
	printf("%d\n",ans);
	return 0;
 } 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值