蓝桥杯2023年第十四届省赛真题-管道
题目描述
有一根长度为 len 的横向的管道,该管道按照单位长度分为 len 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。
一开始管道是空的,位于 Li 的阀门会在 Si 时刻打开,并不断让水流入管道。
对于位于 Li 的阀门,它流入的水在 Ti (Ti ≥ Si) 时刻会使得从第 Li−(Ti−Si) 段到第 Li + (Ti − Si) 段的传感器检测到水流。 求管道中每一段中间的传感器都检测到有水流的最早时间。
输入格式
输入的第一行包含两个整数 n, len,用一个空格分隔,分别表示会打开的阀门数和管道长度。
接下来 n 行每行包含两个整数 Li , Si,用一个空格分隔,表示位于第 Li 段 管道中央的阀门会在 Si 时刻打开。
输出格式
输出一行包含一个整数表示答案。
样例输入
3 10 1 1 6 5 10 2
样例输出
5
提示
对于 30% 的评测用例,n ≤ 200,Si,len ≤ 3000 ;
对于 70% 的评测用例,n ≤ 5000,Si,len ≤ 105 ;
对于所有评测用例,1 ≤ n ≤ 105,1 ≤ Si , len ≤ 109,1 ≤ Li ≤ len,Li−1 < Li
解题思路
本题可用二分法来查找最短时间,属于最大值最小化问题。在最短时间之前,存在传感器没有感应到水流,在最短时间之后,所有传感器都感应到了水流。我们可以把时间跨度拉大,题目描述水管长度为10的9次方,我们可以设置最大时间为2*10^9+1,确保时间跨度足够。接下来使用二分算法,找出mid,由于我们分析的题目是最大值最小化问题,所以,最短时间一定是在右侧区间,故,r为最终解。
实现代码
def check(ans):
res = []
for i in range(n):
if a[i][1] > ans:
continue
l = max(1, a[i][0]-(ans-a[i][1]))
r = min(ll, a[i][0]+(ans-a[i][1]))
res.append([l, r])
res.sort()
if res[0][0] > 1:
return False
rr = res[0][1]
for i in range(1, len(res)):
if res[i][0] > rr and res[i][0] != rr + 1:
return False
else:
rr = max(rr, res[i][1])
if rr < ll :
return False
return True
n, ll = map(int, input().split())
a = []
for _ in range(n):
a.append(list(map(int, input().split())))
l, r = 1, 2*10**9+1
while l + 1 != r:
mid = (l+r)//2
if check(mid):
r = mid
else:
l = mid
print(r)