AcWing 5407. 管道——二分答案
原题链接
中等
//本题要我们求解使得每一段管道都有水流的最短时间T
//时间T可能的取值范围是[0,2e9 - 1]
//在T之前的时刻(即[0, T]),总有部分管道没有水流通过
//在T之后的时刻(即[T, 2e9 - 1]),所有的管道都会有水流通过
//因此我们可以看出要求解的答案T具有明显的“二段性”,
//所以我们可以采取“二分答案”的方法,每一轮二分都能得到一个时刻T0
//基于“在T0时刻是否所有的管道都有水流通过”来判断T0是在[0, T]中,还是在[T, 2e9 - 1]中
//“二分”的一大妙用就在于我们可以为解题带来一个新的条件,
//比如在本题中,我们通过二分答案,为本题带来了时刻T0这一条件
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PII;
const int N = 1e5 + 10;
int n, len;
int le[N], s[N];
struct Qujian
{
LL l, r;
bool operator < (const Qujian &W) const
{
return l < W.l;
}
}qu[N];
LL b_search(LL l, LL r)
{
while(l < r)
{
LL mid = (l + r) >> 1;//假设时间已知
//遍历所有的le[i]和s[i]
int cnt = 0;
for(int i = 1; i <= n; i ++)
{
if(mid >= s[i])
{
LL x = mid - (LL)s[i];
qu[cnt].l = max((LL)1, (LL)le[i] - x);
qu[cnt].r = min((LL)len, (LL)le[i] + x);
cnt ++;
}
}
sort(qu, qu + cnt);
LL sta = -1, en = -1;
for(int i = 0; i < cnt; i ++)
{
auto t = qu[i];
if(t.l <= en + 1)
en = max(en, qu[i].r);
else
{
sta = t.l;
en = t.r;
}
}
if(sta == 1 && en == len) r = mid;
else l = mid + 1;
}
return l;
}
int main()
{
cin >> n >> len;
for(int i = 1; i <= n; i ++)
scanf("%d%d", &le[i], &s[i]);
LL l = 0, r = 2e9 - 1;
LL t = b_search(l, r);
cout << t << endl;
return 0;
}