蓝桥杯-管道

"""
题目来源:
https://www.lanqiao.cn/problems/3544/learning/?page=1&first_category_id=1&name=%E7%AE%A1%E9%81%93
"""
n, length = map(int, input().split())
lis = []
for _ in range(n):
    Li, Si = map(int, input().split())
    lis.append([Li, Si])

# 判断在时间T时能否覆盖整个管道
def check(T):
    res = []
    for Li, Si in lis:
        tmp = T - Si
        # 因为Li管段在Si时间打开, 没有到时间, 阀门是不开的
        if tmp >= 0:
            res.append([Li - tmp, Li + tmp])
    res.sort()

    L0 = res[0][0] # 第一个区间的左端点位置, 也是区间合并后左端点, 不需要进行更新
    # 判断能否覆盖管段左边管段
    if L0 > 1:
      return False
    R0 = res[0][1] # 第一个区间的右端点位置
    for i in range(1, len(res)):
        # 如果下一个区间的左端点位置 <= 前面区间的右端点位置 + 1
        # 则可以将当前区间跟前面的区间合并, 更新区间右端点
        if res[i][0] <= R0 + 1:
            R0 = max(R0, res[i][1])
        else:
            break
    # 判断n个区间合并后能否覆盖右边全部管段
    return R0 >= length

# 对于长度最长为10 ** 9的管道, 当T = 10 ** 10一定可以让所有管段都能监测到水位
# 但是问题是要求最小时间, 那么久不断二分, 求最小的时间让所有管段都能监测到水
l = 0
r = 10 ** 10
while l < r:
    mid = (l + r) // 2
    if check(mid): # 如果该时间符合要求,继续向左寻找更小的数字
        r = mid
    else:
        l = mid + 1
print(l)

"""
# 暴力求解: 枚举每一个阀门让所有管段都监测到水的时间, 然后取最小值, 就是每个管段监测到水的最小时间,
# 要想所有管段都监测到水位, 那么就需要等耗时最长的那个管段监测到水流
# 缺点: 时间复杂度O(nm)只能通过70%, 同时管段的长度10 ** 9, 一部分测试超出了数组的内存大小会出现段错误
import os
import sys

# 请在此输入您的代码
n, length = map(int, input().split())
L, S = [], []
for _ in range(n):
  Li, Si = map(int, input().split())
  L.append(Li - 1)
  S.append(Si)

# dp[i]表示第i管段最早什么时候监测到水流
# 枚举从没个门阀开始, 各个管段监测到水的时间, 不断更新dp
# 要想所有管段都监测到水位, 那么就需要耗时最长的那个管段监测到水位
dp = [float('inf')] * length
for i in range(n):
  Li, Si = L[i], S[i]
  dp[Li] = min(dp[Li], Si)
  for j in range(length):
    dp[j] = min(dp[j], dp[Li] + abs(j - Li))
print(max(dp))
"""

虽然暴力求解不能得到全部的分, 但是做题的时候你很难想到二分求解, 建议先看暴力再看二分求解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武科菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值