一本通題解——1236:區間合併

題目

題目鏈接

一本通OJ:http://ybt.ssoier.cn:8088/problem_show.php?pid=1236

我的OJ:http://47.110.135.197/problem.php?id=4240

題目描述

給定 n 個閉區間 [ai; bi],其中 i=1,2,...,n。任意兩個相鄰或相交的閉區間可以合併爲一個閉區間。例如,[1;2] 和 [2;3] 可以合併爲 [1;3],[1;3] 和 [2;4] 可以合併爲 [1;4],但是 [1;2] 和 [3;4] 不可以合併。 我們的任務是判斷這些區間是否可以最終合併爲一個閉區間,如果可以,將這個閉區間輸出,否則輸出no。

輸入

第一行爲一個整數 n,表示輸入區間的數量。

之後 n 行,在第 i 行上(1 ≤ i ≤ n),爲兩個整數 ai 和 bi,整數之間用一個空格分隔,表示區間 [ai;bi]。

輸出

輸出一行,如果這些區間最終可以合併爲一個閉區間,輸出這個閉區間的左右邊界,用單個空格隔開;否則輸出 no。

樣例輸入

5
5 6
1 5
10 10
6 9
8 10

樣例輸出

1 10

數據範圍

3 ≤ n ≤ 50000

1 ≤ ai ≤ bi ≤ 10000

分析

數學知識

區間一共有兩個座標,即起點座標和終點座標。其中起點座標記爲 ST,終點座標記爲 ED。

假設我們有任意兩個區間 A 和 B,則這兩個區間可以有三種可能關係。

相交

區間 A 和區間 B 有交集,如圖所示。

則有這樣的數學關係:ST_{a} < ST_{b}\leqslant ED_{a}< ED_{b}

不相交

區間 A 和區間 B 沒有交集,如圖所示。

則有這樣的數學關係:ED_{a}<ST_{b}

包含

區間 A 包含區間 B ,如圖所示。

則有這樣的數學關係:ST_{a} \leqslant ST_{b}< ED_{a}\leqslant ED_{b}

題目分析

本題給定了 n 個區間,要求我們判斷這 n 個區間是否可以合併爲一個區間。假設有兩個區間 A 和 B,這兩個區間能合併成一個區間,那麼這兩個區間的關係只能是上面的相交或者包含。如果區間 A  和區間 B 不相交,則必然不能合併。那麼問題就變成如何保證區間 A 在區間 B 的前面,即ST_{a}\leqslant ST_{b}?很簡單,將所有區間進行排序,先按照左端點(起點)大小,再按右端點(終點)大小,進行排序即可。

樣例數據分析

首先將樣例數據排序,變爲如下數據:

1 5
5 6
6 9
8 10
10 10

用一個變量 cur 表示當前操作區間,開始的時候指向第一個區間,即 [1, 5]。用一個變量 next 表示要進行合併操作的區間,目前是 [5, 6]。如下圖所示。

這兩個區間相交,可以合併。這樣 cur 區間變爲 [1, 6],next 區間變爲 [6, 9]。那麼當前數據如下圖所示:

這兩個區間相交,可以合併。這樣 cur 區間變爲 [1, 9],next 區間變爲 [8, 10]。那麼當前數據如下圖所示:

這兩個區間相交,可以合併。這樣 cur 區間變爲 [1, 10],next 區間變爲 [10, 10]。那麼當前數據如下圖所示:

這兩個區間相交,可以合併。這樣 cur 區間變爲 [1, 10]。結束整個過程。

數據範圍分析

從題目中可以知道,n 的最大值爲 50000,座標範圍是 [1, 10000],所以使用 int 表示足夠。

對區間的描述,可以使用 STL 的 pair,也可以使用自定義的 struct。

算法思路

1、讀入所有數據並保存。

2、將所有區間進行排序。

3、遍歷兩個相鄰區間,看能否合併。如果可以合併,則合併區間,繼續遍歷直到最後一個區間。如果不可以合併,則結束程序。

AC 參考代碼

//http://ybt.ssoier.cn:8088/problem_show.php?pid=1236
//區間合併
#include <bits/stdc++.h>
using namespace std;

//區間定義
struct NODE {
    int x;
    int y;
};

const int MAXN = 5e4+4;
NODE data[MAXN] = {};

bool mycmp(const NODE &a, const NODE &b) {
    if (a.x!=b.x) {
        return a.x<b.x;
    } else {
        return a.y<b.y;
    }
}

int main() {
    int n;
    cin >> n;

    int i;
    for (i=0; i<n; i++) {
        cin >> data[i].x >> data[i].y;
    }

    //排序
    sort(data, data+n, mycmp);

    //遍歷
    NODE curr = data[0];
    for (i=1; i<n; i++) {
        if (data[i].x > curr.y) {
            //沒有交集
            cout << "no" << endl;
            return 0;
        } else {
            //包含或者相交關係
            curr.y = max(curr.y, data[i].y);
        }
    }

    cout << curr.x << " " << curr.y << endl;
    
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章