1. 程式人生 > 其它 >【每日一題】DAY8——校門外的樹

【每日一題】DAY8——校門外的樹

技術標籤:演算法學習演算法區間合併地鐵校門外的樹

題目描述

某校大門外長度為L的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是 1 米。

我們可以把馬路看成一個數軸,馬路的一端在數軸0的位置,另一端在 L 的位置;數軸上的每個整數點,即 0,1,2,……,L,都種有一棵樹。

由於馬路上有一些區域要用來建地鐵。

這些區域用它們在數軸上的起始點和終止點表示。

已知任一區域的起始點和終止點的座標都是整數,區域之間可能有重合的部分。

現在要把這些區域中的樹(包括區域端點處的兩棵樹)移走。

你的任務是計算將這些樹都移走後,馬路上還有多少棵樹。

輸入格式

輸入檔案的第一行有兩個整數L和M,L代表馬路的長度,M代表區域的數目,L和M之間用一個空格隔開。

接下來的M行每行包含兩個不同的整數,用一個空格隔開,表示一個區域的起始點和終止點的座標。

輸出格式

輸出檔案包括一行,這一行只包含一個整數,表示馬路上剩餘的樹的數目。

資料範圍

1 ≤ L ≤ 10000 1≤L≤10000 1L10000
1 ≤ M ≤ 100 1≤M≤100 1M100

輸入樣例:

500 3
150 300
100 200
470 471

輸出樣例:

298

思路

這道題有多種解法,這裡我們使用兩種:

第一種:暴力模擬法

  1. 開闢一個長度為 L + 1 的 bool 陣列,每個元素代表樹的狀態: true: 有樹, false:沒有樹。
  2. 遍歷每條地鐵,把地鐵區間內的樹砍掉,即對應陣列元素置為 false。
  3. 統計陣列中還有多少個 true ,就是還是剩多少棵樹。
#include <iostream>
using namespace std;

const int N = 10010;
bool tree[N];//儲存樹的陣列

int main()
{
    int l, m;
    cin >> l >> m;
    for(int i = 0; i<= l; i++) tree[i] = true;//路區間內有樹,a[i] :true
    while(m--)
    {
        int st, end;
        cin >> st >> end;
        for
(int i = st; i <= end; i++) tree[i] = false;//地鐵覆蓋區間,a[i]:false } int res = 0; for(int i = 0; i <= l; i++) res += tree[i];//統計還剩多少樹。 cout << res; }

方法二:區間合併

  1. 將要砍掉樹的區間合併在一起,合併後的區間沒有重合部分。例如:[13]和[35] 合併成 [1~5]。
  2. 數的總數 - 合併後所有區間覆蓋的點數 = 剩餘樹的數量。

區間合併:

  1. 將區間按左端點升序排序。
  2. 從第一個區間開始,如果該區間的右端點大於後面相鄰區間的左端點,當前區間右端點更新為:該區間右端點和相鄰區間右端點最大值。直到不能繼續合併,然後開始後面區間合併。
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 110;

int n, m;
pair<int, int> undg[N];//儲存地鐵區間
int main()
{
    cin >> n >> m;
    int res = n + 1;
    for(int i = 0; i < m; i++ ) cin >> undg[i].first >> undg[i].second;
    sort(undg,undg + m);//按照左端點排序
    int st = undg[0].first, ed = undg[0].second;//起始區間
    for(int i = 1; i < m; i++)
    {
        if(ed >= undg[i].first) ed = max(ed, undg[i].second);//的右端點大於後面相鄰區間的左端點,合併在一起
        else// 否則重新開始合併
        {
            res -= ed - st + 1;//減去當前區間的樹的數量
            st = undg[i].first;//新維護區間的左端點
            ed = undg[i].second;//新維護區間的右端點
        }
    }
    res -= ed - st + 1;//減去最後一個地鐵區間的樹木
    cout << res<< endl;
}