1. 程式人生 > 其它 >cf612 D. The Union of k-Segments(被至少K條線段覆蓋的所有區間)

cf612 D. The Union of k-Segments(被至少K條線段覆蓋的所有區間)

題意:

給定n條線段,如果一個實數點被至少K條線段覆蓋,稱為好點。輸出一列總長度最小的、包含所有好點的閉區間

輸入均為整數

思路:

傳世經典題。

差分思想:想象一個實數軸,所有線段左端點座標處打上1標記,右端點打上-1。對所涉所有座標排序,計算字首和 k。根據當前的 k 可以判斷當前點被覆蓋的情況

int n, K; vector<PII> ve; //位置,型別
vector<PII> ans; //答案
signed main() {
    iofast;
    cin >> n >> K;
    for(int i = 1; i <= n; i++) {
        int l, r; cin >> l >> r;
        ve.pb({l, 1}), ve.pb({r, -1});
    }
    sort(all(ve), [](PII &x, PII &y) { //保證先加再減
         return x.fi != y.fi ? x.fi < y.fi : x.se > y.se;
    });
    int k = 0; for(auto &[p,t] : ve) {
        if(k == K - 1 && t == 1) ans.pb({p,0});
        if(k == K && t == -1) ans.back().se = p;
        k += t;
    }
    cout << ans.size() << endl;
    for(auto &[l,r] : ans) cout << l << ' ' << r << endl;
}

細節可以稍有不同:

    for(int i = 1; i <= n; i++) {
        int l, r; cin >> l >> r;
        ve.pb({l, 1}), ve.pb({r + 1, -1});        //這樣
    }
    sort(all(ve));                                //這樣
    int k = 0; for(auto &[p,t] : ve) {
        if(k == K - 1 && t == 1) ans.pb({p,0});
        if(k == K && t == -1) ans.back().se = p-1;//這樣
        k += t;
    }