灌溉农田贪心和社交距离I贪心对比(原标签可以用二分答案)

社交距离 I

一种新型疾病,COWVID-19,开始在全世界的奶牛之间传播。

Farmer John 正在采取尽可能多的预防措施来防止他的牛群被感染。

Farmer John 的牛棚是一个狭长的建筑物,有一排共 N 个牛栏。

有些牛栏里目前有奶牛,有些目前空着。

得知“社交距离”的重要性,Farmer John 希望使得 D 尽可能大,其中 D 为最近的两个有奶牛的牛栏的距离。

例如,如果牛栏 3 和 8 是最近的有奶牛的牛栏,那么 D=5。

最近两头奶牛新来到 Farmer John 的牛群,他需要决定将她们分配到哪两个之前空着的牛栏。

请求出他如何放置这两头新来的奶牛,使得 D 仍然尽可能大。

Farmer John 不能移动任何已有的奶牛;他只想要给新来的奶牛分配牛栏。

输入格式
输入的第一行包含 N。

下一行包含一个长为 N 的字符串,由 0 和 1 组成,描述牛棚里的牛栏。

0 表示空着的牛栏,1 表示有奶牛的牛栏。

字符串中包含至少两个 0,所以有足够的空间安置两头新来的奶牛。

输出格式
输出 Farmer John 以最优方案在加入两头新来的奶牛后可以达到的最大 D 值(最近的有奶牛的牛栏之间的距离)。

数据范围
2≤N≤105
输入样例:
14
10001001000010
输出样例:
2
样例解释
在这个例子中,Farmer John 可以以这样的方式加入奶牛,使得牛栏分配变为 10x010010x0010,其中 x 表示新来的奶牛。

此时 D=2。

不可能在加入奶牛之后取到更大的 D 值。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2e5+3;
int n;
char s[N];
int a[N];


int main()
{
    cin>>n;
    int cnt=0;
    cin>>s + 1;
    int y = 0;
    for(int i = 1;i <= n ; i++)
    {
        if(s[i] == '1')a[++cnt] = i;
    }
    if(!cnt)
    {
        cout<<n - 1<<endl;
        return 0;
    }
    
    int minx=N;
    for(int i = 1;i < cnt;i++)
    {
        minx = min(a[i+1] - a[i] , minx);
    }
    
    y =  max((a[1] - 1)/2 , (n - a[cnt])/2);
    
    for(int i = 1; i<cnt;i++)
    {
        y = max(y , (a[i + 1] - a[i])/3);
    }
    int y1 = a[1] - 1,y2 = n - a[cnt];
    if(y1<y2)swap(y1,y2);
    for(int i = 1;i<cnt;i++)
    {
        int x = (a[i + 1] - a[i])/2;
        if(x>y1)y2 = y1 , y1 = x;
        else if(x>y2)y2 = x;
    }
    y = max(y,y2);
    y = min(y,minx);
    cout<<y;
    
    
    return 0;
}

重点在于分类的区别点在哪,按在不在同一个区间划分仅仅就只需要讨论两种类型就行(y总nb)

农田灌溉

农夫约翰有 n 片连续的农田,编号依次为 1∼n。

其中有 k 片农田中装有洒水器。

装有洒水器的农田的编号从小到大依次为 x1,x2,…,xk。

在某个炎热的中午,约翰觉得是时候给他的所有农田浇水了。

每个洒水器在打开以后,向两侧方向洒水,并且随着开启时间延长,有效覆盖距离也不断增长。

具体来说,我们将第 xi 片农田中的洒水器打开,经过 1 秒后,第 xi 片农田被其覆盖,经过 2 秒后,第 [xi−1,xi+1] 片农田被其覆盖,经过 j 秒后,第 [xi−(j−1),xi+(j−1)] 片农田被其覆盖。

注意,每个洒水器的有效覆盖距离在每经过整数秒后,才会有所增长。

例如,经过 2.5 秒后,被第 xi 片农田中的洒水器覆盖的农田仍是第 [xi−1,xi+1] 片农田,而不是第 [xi−1.5,xi+1.5] 片农田。

现在,约翰将所有洒水器同时打开,请问经过多少秒后,所有农田均被灌溉。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含两个整数 n,k。

第二行包含 k 个整数 x1,x2,…,xk。

输出格式
每组数据输出一行答案。

数据范围
前三个测试点满足 1≤n≤5,
所有测试点满足 1≤T≤200,1≤n≤200,1≤k≤n,1≤xi≤n,xi−1<xi,T 组数据的 n 相加之和不超过 200。

输入样例:
3
5 1
3
3 3
1 2 3
4 1
1
输出样例:
3
1
4

{
    
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>k;
        int maxn=0;
        for(int i =1;i<=k;i++)
        {
            cin>>a[i];
        }
        maxn = max(a[1],n-a[k]+1);
        for(int i = 1;i<=k-1;i++)
        {
            int j = i + 1;
                int x = a[j] - a[i] + 1;
                maxn = max(maxn,(x+1)/2);
        }
        
        cout<<maxn<<endl;
    }
    
    return 0;
}

这道题我先想到最长的距离和最长任务周期和最长浇水时间是一样的,都取决于最长的一段,而这道题没有两头牛,直接对比每个区间两个水龙头同时浇灌时,肯定取到中点的距离上取整。(上面一题是下取整)

但这两题都可以用二分来做,思路就是枚举答案区间,如果枚举的答案满足要求,那么就可以枚举更加贪心的答案区间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值