2. 管道-二分

2.管道 - 蓝桥云课 (lanqiao.cn)

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
//存阀门,li表示第几段,si表示什么时刻打开
struct fa{
	int li;
	int si;
}fa[100005];
//存阀门打开后,水流的区间,ll是左区间,rr是右区间
struct qu{
	int ll;
	int rr;
}qujian[100005];
//n是有几个阀门,len是管道的长度
int n,len;
//排序,从小到大排序,先排左边界,再排右边界
bool cmp(qu a,qu b){
	if(a.ll<b.ll) return true;
	else if(a.ll==b.ll){
		return a.rr<b.rr;
	}
	else return false;
}
//检查该ti时刻,水流能不能覆盖管道
bool check(int ti){
	int cnt=0;//该ti时刻能打开的阀门数量
	for(int i=0;i<n;i++){
		if(fa[i].si>ti) continue;//当前时刻,该阀门还没到点,还没打开,所以跳过去
		//存区间,代入题目的公式即可
		qujian[cnt].ll=fa[i].li-(ti-fa[i].si);
		qujian[cnt].rr=fa[i].li+(ti-fa[i].si);
		cnt++;
	}
	sort(qujian,qujian+cnt,cmp);//区间排序,从小到大排序,先排左边界,再排右边界
	if(qujian[0].ll>1) return false;//如果管道最左边都覆盖不了,那么直接return false
	int last=-1;//last记录当前覆盖的管道最右侧,每遍历一个区间,更新一下
	for(int i=0;i<cnt;i++){
		if(qujian[i].ll>last+1) return false;//如果当前的区间最左端,无法覆盖掉目前水流的右侧
		//即水流覆盖范围中间有空白,那么return false
		last=max(qujian[i].rr,last);//更新一下last,取最大值
	}
//	cout<<"%";
	if(last<len) return false;//如果管道最右边覆盖不了,return false
	return true;
}
void solve(){
	cin>>n>>len;
	for(int i=0;i<n;i++){
		cin>>fa[i].li>>fa[i].si;//存阀门
	}
	//二分答案,r取这个值是因为,如果管道最左侧的阀门在1e9时刻打开
	//然后要覆盖到最右侧,但是管道长度1e9,那么总时长得2e9
	int l=0,r=2000000005;
	while(l<r){
		int mid=l+r>>1;
		if(check(mid)){
			r=mid;
//			cout<<"&";
		}else{
//			cout<<"*";
			l=mid+1;
		}
	}
	cout<<l;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	solve();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值