管道(蓝桥杯)

有一根长度为 \(len\) 的横向的管道,该管道按照单位长度分为 \(len\) 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。

一开始管道是空的,位于 \(L_i\) 的阀门会在 \(S_i\) 时刻打开,并不断让水流入管道。

对于位于 \(L_i\) 的阀门,它流入的水在 \(T_i\)\(T_i \ge S_i\))时刻会使得从第 \(L_i-(T_i-S_i)\) 段到第 \(L_i+(T_i-S_i)\) 段的传感器检测到水流。

求管道中每一段中间的传感器都检测到有水流的最早时间。

输入格式

输入的第一行包含两个整数 \(n,len\),用一个空格分隔,分别表示会打开的阀门数和管道长度。

接下来 \(n\) 行每行包含两个整数 \(L_i,S_i\),用一个空格分隔,表示位于第 \(L_i\) 段管道中央的阀门会在 \(S_i\) 时刻打开。

输出格式

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

数据范围

对于 \(30\%\) 的评测用例,\(n ≤ 200\)\(S_i,len ≤ 3000\)
对于 \(70\%\) 的评测用例,\(n ≤ 5000\)\(S_i,len ≤ 10^5\)
对于所有评测用例,\(1 ≤ n ≤ 10^5\)\(1 ≤ S_i,len ≤ 10^9\)\(1 ≤ L_i ≤ len\)\(L_{i-1} < L_i\)

输入样例:

3 10
1 1
6 5
10 2

输出样例:

5
#include <bits/stdc++.h>
#define x first
#define y second
#define int long long

using namespace std;

const int N = 1e5 + 10;
typedef pair<int, int> PII;
int n, m;
PII s[N], q[N];

bool check(int u)
{
    int cnt = 0;
    for(int i = 0; i < n; i ++ )
    {
        int L = s[i].x, S = s[i].y;

        if(S <= u) // 当前时刻u大于等于水阀打开时刻S
        {
            int t = u - S;
            int l = max((int)1, L - t), r = min(m, L + t); // 水在u时刻所能覆盖的范围
            q[cnt ++ ] = {l, r};
        }
    }

    sort(q, q + cnt);

    int l = -1, r = -1;
    for(int i = 0; i < cnt; i ++ )
    {
        if(q[i].x <= r + 1) r = max(r, q[i].y); // 合并u时刻水覆盖的区域
        else l = q[i].x, r = q[i].y;
    }
    return l == 1 && r == m;
}

signed main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ ) cin >> s[i].x >> s[i].y;

    int l = 0, r = 2e9;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }

    cout << l << endl;
}
posted @ 2024-03-20 20:39  Hamster~~  阅读(30)  评论(0)    收藏  举报