---
# System prepended metadata

title: 'Zerojudge b966: APCS第三題 線段覆蓋長度'

---

# Zerojudge b966: APCS第三題 線段覆蓋長度
> **Link:** [Zerojudge b966](https://zerojudge.tw/ShowProblem?problemid=b966)
---
## Description:

給定一維座標上一些線段，求這些線段所覆蓋的長度，注意，重疊的部分只能算一次。

例如給定 4 個線段：$(5, 6)、(1, 2)、(4, 8)、(7, 9)$，如下圖，線段覆蓋長度為 6 。

![題目示意圖](https://i.imgur.com/o0xexNz.png)

---
## Input Format & Output Format


|                                                                                                                                                                                                        Input Format                                                                                                                                                                                                        |                        Output Format                         |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------:|
| 第一列是一個正整數 $N$ ，表示此測資有 $N$ 個線段。接著的 $N$ 列每一列是一個線段的開始端點座標整數值 $L$ 和結束端點座標整數值 $R$ ，開始端點座標值小於等於結束端點座標值，兩者之間以一個空格區隔。其中30%的測資滿足， $N < 100 ， 0 ≤ L , R < 1000$ ，並且線段沒有重疊。其中70%的測資滿足， $N < 100 ， 0 ≤ L , R < 1000$ ，並且線段可能重疊。其中100%的測資滿足， $N < 10000 ， 0 ≤ L , R < 10000000$ ，並且線段可能重疊。 | 輸出其總覆蓋的長度。本題為嚴格比對，請務必按照說明進行輸出。 |
|                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                              |

---

## Sample Input & Output

**Input:**
輸入範例一：
5
160 180
150 200
280 300
300 330
190 210

輸入範例二：
1
120 120

**Output:**
輸出範例一：
110

輸出範例二：
0

---
## 解題歷程

**【解題想法】**:排序
**【Tag】**:排序(Sorting)、貪心(Greedy)、掃描線(Sweep Line)
* {x, y}：每個線段的「起點」座標 x 和「終點」座標 y。
* 排序：x 由小到大排序，x 相同的話，y 由大到小排序。
* 變數 left：目前線段的「起點」座標。
* 變數 right：目前線段的「終點」座標。

作法1-Sweep Line : 
```cpp=
#include <bits/stdc++.h>
using namespace std;
#define AC ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define pii pair<int,int> 
#define f first
#define s second
bool cmp(pii a,pii b) {
    if(a.f==b.f) return a.s>b.s;
    else return a.f<b.f;
}
int main() {
    AC
    int n,x,y;
    while(cin>>n) {
        vector<pii> v;
        for(int i=0;i<n;i++) {
            cin>>x>>y;
            v.push_back({x,y});
        }
        sort(v.begin(),v.end(),cmp);
        int left=0,right=0,ans=0;
        for(int i=0;i<v.size();i++) {
            if(v[i].f>=left) {
                ans+=(right-left);
                left=v[i].f;
                right=v[i].s;
            }else if(v[i].s>left){
                right=v[i].s;
            }
        }
        ans+=(right-left);
        cout<<ans<<'\n';
    }
    return 0;
}
```
作法2-把線段的開始端點和結束端點視為獨立的evnet，記錄覆蓋的線段數 : 
```cpp=
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
 
int main() {
    int N, L, R;
    cin >> N;
    vector<pair<int,int>> v;
    for (int i = 0; i < N; i++) {
        cin >> L >> R;
        //把線段的開始端點和結束端點視為獨立的evnet
        //在線段的開始端點L處，event +1
        v.push_back({L, 1});
        //在線段的結束端點R處，event -1
        v.push_back({R, -1});
    }
    sort(v.begin(), v.end());
    //now指向目前檢視的event
    //event為該座標點i, 對應一個左閉由開區間[i, i+1), 共被幾段線段覆蓋
    int now = 0, event = 0, ans = 0;
    for (int i = 0; i <= 1e7; i++) {
        while (now < (int)v.size() && v[now].first == i) {
            event += v[now].second;
            now++;
        }
        if (event > 0) {
            ans++;
        }
    }
    cout << ans << "\n";
    return 0;
}
```