2121: 管道(New Online Judge)

2121: 管道(New Online Judge)

题目描述

有一根长度为 len 的横向的管道,该管道按照单位长度分为 len 段。每一段的中央有一个可开关的阀门和一个检测水流的传感器。一开始管道是空的,位于 Li 的阀门会在 Si 时刻打开,并不断让水流入管道。对于位于 Li 的阀门,它流入的水在 Ti (Ti≥Si) 时刻会使得从第 Li-(Ti-Si) 段到第 Li+(Ti-Si) 段的传感器检测到水流。
求管道中每一段中间的传感器都检测到有水流的最早时间。

输入

输入的第一行包含两个整数 n, len,用一个空格分隔,分别表示会打开的阀门数和管道长度。接下来 n 行每行包含两个整数 Li, Si,用一个空格分隔,表示位于第 Li 段管道中央的阀门会在 Si 时刻打开。
对于 30% 的评测用例,n ≤ 200,Si, len ≤ 3000 ;
对于 70% 的评测用例,n ≤ 5000,Si, len ≤ 100000 ;
对于 100% 的评测用例, 1 ≤ n ≤ 100000 , 1 ≤ S i , l e n ≤ 1 0 9 , 1 ≤ L i ≤ l e n , L i − 1 < L i 1 ≤ n ≤ 100000,1 ≤ Si, len ≤ 10^9,1 ≤ Li ≤ len,Li-1 < Li 1n1000001Si,len1091LilenLi1<Li

输出

输出一行包含一个整数表示答案。

样例输入

3 10
1 1
6 5
10 2

样例输出

5

题解1(C++ 版本1)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;

int n, len, s[N], Len[N];

bool check(LL x){
	vector<pair<LL,LL>> interval;
	int cnt = 0;
	for(int i = 1; i <= n; i++){
		if(x < s[i]) continue; //要保证ti>=si 
		//位于Li的阀门,可以使得传感器检测到的左边界和右边界 
		interval.push_back({Len[i] - (x - s[i]), Len[i] + (x - s[i])});
	}
	sort(interval.begin(), interval.end());
	if(interval.size() == 0 || interval[0].first > 1) return false;
	
	LL right = interval[0].second;
	for(int i = 1; i < (int)interval.size(); i++){
		if(interval[i].first > right + 1) break;
		right = max(right, interval[i].second);
	}
	return right >= len;
}
int main(){
	scanf("%d%d", &n, &len);
	
	for(int i = 1; i <= n; i++){
		scanf("%d%d", &Len[i], &s[i]);
	}
	LL L = 0, R = 2e9 + 7, mid;
	while(L + 1 < R){
		mid = (L + R)/2;
		if(check(mid)) R = mid; // 二分答案 
		else L = mid;
		//printf("L =%lld R=%lld mid = %lld", L, R, mid);
	}
	printf("%lld\n", R);
	return 0;
}

题解2(C++版本2)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
const LL INF = 1e9;
int n, len, s[N], Len[N];

bool check(LL x){
	int cnt = 0;
	LL last_L = 2, last_R = 1LL;
	for(int i = 1; i <= n; i++){
		if(x < s[i]) continue; //要保证ti>=si 
		//位于Li的阀门,可以使得传感器检测到的左边界和右边界 
		cnt++;
		LL left = 1LL*Len[i] - min(INF, x - s[i]);
		LL right = 1LL*Len[i] + min(INF, x - s[i]);
		if(left < last_L) last_L = left, last_R = max(right, last_R);
		else if(left <= last_R + 1) last_R = max(right, last_R);
	}
	if(!cnt) return false;
	
	return last_L <= 1 && last_R >= len;
}
int main(){
	scanf("%d%d", &n, &len);
	for(int i = 1; i <= n; i++) scanf("%d%d", &Len[i], &s[i]);

	LL L = 0, R = 2e9 + 7, mid;
	while(L + 1 < R){
		mid = (L + R)/2;
		if(check(mid)) R = mid; // 二分答案 
		else L = mid;
		//printf("L =%d R=%d mid = %d\n", L, R, mid);
	}
	printf("%d\n", R);
	return 0;
}

题解3 (C++版本3)

#include<bits/stdc++.h>
using namespace std;
#define int long long // #define int long long ,main函数要改成有符号型 signed main()
const int N = 1e5 + 10;
const int INF = 1e9;
int n, len, s[N], Len[N];

bool check(int x){
	int cnt = 0;
	int last_L = 2, last_R = 1;
	for(int i = 1; i <= n; i++){
		if(x < s[i]) continue; //要保证ti>=si 
		//位于Li的阀门,可以使得传感器检测到的左边界和右边界 
		cnt++;
		int left = Len[i] - min(INF, x - s[i]);
		int right = Len[i] + min(INF, x - s[i]);
		if(left < last_L) last_L = left, last_R = max(right, last_R);
		else if(left <= last_R + 1) last_R = max(right, last_R);
	}
	if(!cnt) return false;
	
	return last_L <= 1 && last_R >= len;
}
signed main(){
	scanf("%d%d", &n, &len);
	for(int i = 1; i <= n; i++) scanf("%d%d", &Len[i], &s[i]);

	int l = 0, r = 2e9, ans = -1;
    while(l <= r){
        int mid = ((r - l) >> 1) + l;
        if(check(mid))ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    printf("%d\n", ans);
	return 0;
}
  • 63
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值