二分 - Enduring Exodus - CodeForces - 655C

二分 - Enduring Exodus - CodeForces - 655C

题意:

首 行 输 入 包 括 两 个 整 数 n 和 m , 分 别 为 房 间 的 数 量 和 牛 的 数 量 。 首行输入包括两个整数n和m,分别为房间的数量和牛的数量。 nm

第 二 行 包 含 一 个 长 度 为 n 的 01 串 , ′ 0 ′ 表 示 房 间 为 空 , ′ 1 ′ 表 示 房 间 不 空 。 第二行包含一个长度为n的01串,'0'表示房间为空,'1'表示房间不空。 n0101

现 有 一 人 与 m 头 牛 , 要 住 在 这 n 个 房 间 中 的 空 房 间 中 , 要 求 使 得 所 有 牛 中 距 离 主 人 房 间 最 远 的 距 离 尽 量 小 。 现有一人与m头牛,要住在这n个房间中的空房间中,要求使得所有牛中距离主人房间最远的距离尽量小。 mn使

求 出 这 个 最 小 最 远 距 离 。 求出这个最小最远距离。

数据范围:

1 < = n , m < = 100000 T i m e   l i m i t : 2000 m s , M e m o r y   l i m i t : 262144 k B 1<=n,m<=100000\\Time\ limit:2000 ms,Memory \ limit:262144 kB 1<=n,m<=100000Time limit2000msMemory limit262144kB

Examples

Input:
7 2
0100100
_______
Output:
2

Input:
5 1
01010
_______
Output:
2

Input:
3 2
000
_______
Output:
1

分析:

若 最 远 距 离 为 k 时 能 够 住 下 , 那 么 最 远 距 离 为 k + 1 时 也 一 定 能 够 住 下 。 若最远距离为k时能够住下,那么最远距离为k+1时也一定能够住下。 kk+1

因 此 二 分 答 案 。 因此二分答案。

枚 举 主 人 的 位 置 i , 接 着 二 分 最 远 距 离 m i d , 若 m i d 可 行 则 r = m i d , 反 之 l = m i d + 1 。 枚举主人的位置i,接着二分最远距离mid,若mid可行则r=mid,反之l=mid+1。 imidmidr=midl=mid+1

关 键 问 题 在 于 c h e c k 函 数 如 何 写 , 判 断 m i d 是 否 可 行 。 关键问题在于check函数如何写,判断mid是否可行。 checkmid

对 于 枚 举 的 主 人 位 置 i , 判 断 一 下 [ i − m i d , i + m i d ] 这 个 区 间 内 是 否 存 在 m + 1 个 0 , 若 存 在 , 说 明 m i d 可 行 。 对于枚举的主人位置i,判断一下[i-mid,i+mid]这个区间内是否存在m+1个0,若存在,说明mid可行。 i[imid,i+mid]m+10mid

因 为 要 频 繁 的 查 询 某 段 区 间 内 ′ 0 ′ 的 数 量 , 故 先 用 前 缀 和 预 处 理 区 间 ′ 0 ′ 的 数 量 。 因为要频繁的查询某段区间内'0'的数量,故先用前缀和预处理区间'0'的数量。 00

代码:

#include 
#include 
#include 
#include 
#include 
#include 

#define ll long long
#define P pair
#define l first
#define r second
#define inf 0x3f3f3f3f

using namespace std;

const int N = 100010;

int n,m,sum[N];
char s[N];

bool check(int pos,int len)
{
    int l=max(1,pos-len),r=min(n,pos+len);
    return (sum[r]-sum[l-1]>=m+1);
}

int main()
{
    cin>>n>>m;
    scanf("%s",s+1);
    for(int i=1;s[i];i++)
            sum[i]=sum[i-1]+(s[i]=='0');

    int res=n;
    for(int i=1;i<=n;i++)
        if(s[i]=='0')
        {
            int l=1,r=n;
            while(l<r)
            {
                int mid=l+r>>1;
                if(check(i,mid)) r=mid;
                else l=mid+1;
            }
            res=min(res,l);
        }

    cout<<res<<endl;

    return 0;
}

你可能感兴趣的:(二分)