6.24 區間合併

yyyne發表於2024-06-24

這部分比較簡單
題目:

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;
}

相關文章