POJ 2456 && SPOJ–AGGRCOW 二分法

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).
His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

t – the number of test cases, then t test cases follows.
* Line 1: Two space-separated integers: N and C
* Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

For each test case output one integer: the largest minimum distance.

Example

Input:

1
5 3
1
2
8
4
9

Output:

3

Output details:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8,
resulting in a minimum distance of 3.

————————————————————————————————————————————————————————

  这是心态爆炸比赛的第三题,我看了这道题,机智的把这道题给抽象化成为给你一个序列有n-1个元素,序列中每个元素是相邻两个小屋的距离,然后你对于每个元素的操作是可以把这个元素和相邻的元素合并,问合并到c个元素时可以达到的最大的最小元素是多少。

  然后每次找到最小的元素,并将它们和左右两边中较小的一个元素合并,检查数量有没有到c,没有的话继续……】

  然后可想而知这个抽象结构对于问题的解决方式相比二分查找慢多少……不过我突然发现这个思路虽然不能拿来做题但是可以拿来坑人哎!你看看这题面和二分根本没有关系吧!

  真是开心……个鬼啊……

  好了我们来讲讲题面

  这道题就是用二分来做的,至于为什么没第一眼想到二分,是因为我已经好久没有接触过二分的题目了,对于10^9进行二分搜索,每次判断一下,log2(10^9)差不多是33左右,也就是说进行33次判断无论如何都能找到目标。

  然后这里关于二分的边界需要特判一下,除了lef为1的情况以外,每次的开始,lef左边的那个数必然是满足让全部牛住进去的条件的,但是右边有可能会存在满足条件且更大的数,这个状况一直持续到lef和rig是相邻的情况为止,因为二分的特性,rig的右边不可能存在满足条件且更大的数字,那么只有rig本身是一种可能,这时候就特判一下,如果rig满足条件,输出rig,不然输出lef.

_____________________________________________code_____________________________________________

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<queue>
#include<climits>
#include<map>
#include<stack>
#include<cmath>
#define file_in freopen("in.txt","r",stdin)
#define MAX 200000
#define maxn 5005
using namespace std;
#define LL int
#define FF(x,y) for(int i=x;i<y;i++)
vector<int>sta;
int s, c;
int bin(int tar)
{
    int temp = sta[0];
    int cnt = 0;
    for (int i = 1; i < s; i++)
    {
        if (sta[i] - temp >= tar)
        {
            temp = sta[i];
            cnt++;
        }
        if (cnt == c-1)
            return 1;
    }
    return 0;
}
void solve()
{
    int lef = 1, rig = sta[s - 1];
    while (1)
    {
        int mid = (lef + rig) >> 1;
        int res = bin(mid);
        if (lef == rig)
        {
            if (res)
            {
                printf("%d\n", lef);
                return;
            }
            else
            {
                printf("%d\n", lef - 1);
                return;
            }
        }
        if (res)
            lef = mid + 1;
        else
            rig = mid - 1;
       
    }   
}
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d %d", &s, &c);
        sta.resize(s);
        for (int i = 0; i < s; i++)
            scanf("%d", &sta[i]);
        sort(sta.begin(), sta.end());
        solve();
    }
}
/*
Example

Input:

1
5 3
1
2
8
4
9
Output:

3
*/

转载于:https://www.cnblogs.com/stultus/p/6474445.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值