P3853 [TJOI2007]路标设置

在这里插入图片描述
在这里插入图片描述
很水的一道题?为什么我觉得很难??

思路是二分,二分谁呢?
题目的意思是给一段区间,已经插了几个点了,然后再插几个点,问使所有小区间的最大值最小的这个最大值是多少,即空旷指数
做法非常巧妙。
要求的是这个最大值,就能二分查找最大值。
左右端点?
l=0没话说,r=len区间长度也没话说。
但是l<r的时候,r不需要加1(证明过了能AC),因为最右区间端点已经有路标了。这个无所谓
所以思路就是二分这个所有小区间的最大值。
但是也不是直接二分答案,而是通过路标的数量来间接计算:假设设置一个mid作为空旷指数,如果根据这个空旷指数算出来的路标数大于题目给的路标数,说明空旷指数太小了,即所有小区间的最大值设置的太小了,这就和空旷指数联系起来了。所以,l=mid+1.
反之如果根据这个空旷指数算出来的路标数小于等于题目给的路标数,说明空旷指数正好或者太大了,需要小一点,即r=mid-1.
好,其实二分的关键出在为什么是大于和小于等于而不是大于等于和小于。大于是路标大于,实际上是空旷指数小于,小于等于也是路标小于等于,实际上是空旷指数大于等于:所以就是分成了小于和大于等于。。。。。。。
然后就是求大于等于的最小值了。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1011000;
int len,n,m; //公路长度,原有路标数,可增加的路标数
int a[N];
bool check(int mid)
{
    int cnt=0;
    for(int i=2;i<=n;i++)
    {
            cnt+=(a[i]-a[i-1]) / mid;
            if((a[i]-a[i-1]) % mid==0) //a[i] - a[i-1] 必须加括号!!!
                --cnt;
        if(cnt>m) return false;//需要的路标数大于给的,设置的空旷指数太小,需要放大 a[mid] < target
    }
    return true; //cnt<=m,即a[mid] >=target
}
int main()
{
    cin>>len>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    int l=0,r=len;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(check(mid)) r=mid-1; // 即a[mid] >=target,所以return r是小于,l是大于等于,题目要求大于等于
        else l=mid+1;
    }
    cout<<l;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值