這部分比較簡單
題目:
https://www.acwing.com/problem/content/1345/
https://www.acwing.com/problem/content/424/
二分和區間和並結合:https://www.acwing.com/problem/content/5410/
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
typedef pair<int, int> PII;
PII a[N];
int n, len;
// 需要吧中間時刻轉化為時刻用到
bool check(LL mid){
vector<PII> segs;
//得到兩者的區間位置
for(int i=0;i<n;i++){
int l = a[i].first, s = a[i].second;
if(s<=mid){
int left = max(1ll, l - mid + s), right = min((LL)len, l + mid - s);
segs.push_back({left,right});
}
}
int cnt = segs.size();
sort(segs.begin(), segs.end()); // 按左端點從小到大排序
if(segs.empty()) return false;
if(segs[0].first > 1) return false;
int dr = segs[0].second;
// 判斷在不在管道內
for(int i=1;i<cnt;i++){
// 判斷是否只有一個區間
if(segs[i].first > dr + 1) return false;
dr = max(dr, segs[i].second);
}
return dr == len;
}
int main(){
scanf("%d%d", &n, &len);
for(int i = 0; i < n; i ++)
{
int l, s;
scanf("%d%d", &l, &s);
a[i] = {l, s};
}
LL l=1,r = 2e9;
// 二分法 二分的是可滿足的時刻;
while(r>l){
LL mid = l + r >> 1; // 相加過程中可能會爆int,記得要開long long
if( check(mid) ) r = mid;
else l = mid + 1;
}
printf("%lld",l);
return 0;
}