# **2016 3月 APCS 實作三 線段覆蓋長**
:::warning
題目:
給定一維座標上一些線段,求這些線段所覆蓋的長度,注意,重疊的部分只能算一次。
例如給定 4 個線段:(5, 6)、(1, 2)、(4, 8)、(7, 9),如下圖,線段覆蓋長度為 6 。
![image.png](https://hackmd.io/_uploads/H1Ert-vma.png)
第一列是一個正整數 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 ,並且線段可能重疊。
https://zerojudge.tw/ShowProblem?problemid=b966
:::
這題我用到 ==vector動態陣列==做,並找出所有線段裡最遠的點(max),以它為基準把他想像成一個箱子(長度為max),然後把繩子都疊上去
******
**首先引入vector標頭檔**
```cpp=
#include <iostream>
#include <vector> //vector
using namespace std;
```
***
**宣告題目需要的變數**
```cpp=
vector <int> A; //儲存每條繩子兩端點的陣列
int n, ans=0, max=0;
```
***
**輸入**
```cpp=
cin >> n;
for(int i=0;i<2*n;i++)
{
int x;
cin >> x;
A.push_back(x); //將x元素放進A陣列裡(接在上一個元素後面)
if(x>max)//找全部線段裡最遠的點(max)
max = x;
}
```
重複2n次是因為一條繩子有兩個端點,n條就是2*n個端點( A[ 0 ] , A[ 1 ]為第一條繩子的兩端點,A[ 2 ] , A[ 3 ]為第二條繩子兩端點...)
並在過程中就找出最大值
***
**宣告一個大小為max的陣列(A1),並把每一格都設成-1**
```cpp=
vector <int> A1 (max, -1);
```
***
**開始把每條繩子都放在新陣列裡**
``` cpp=
for(int i=0;i<=2*n;i+=2)
{
for(int j=A[i];j<A[i+1];j++)
{
A1[j] = 1;
}
}
```
==外層迴圈== : A[ i ]為每條線段左邊的端點(所以才是i+=2)
==內層迴圈== : j把每條繩子左邊端點( A[ i ] ) 到 右邊端點( A[ i + 1 ] )設成1
這樣即使有覆蓋的地方就會保持1不變了
***
接著用一個for跑完整條繩子,如果A1[ i ]是1那就把ans+1
```cpp=
for(int i=0;i<=max;i++)
{
if(A1[i]==1)
ans++;
}
cout << ans;
```
最後輸出ans
***
:::success
完整程式碼
:::
```cpp=
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int> A;
int n,ans=0,max=0;
cin >> n;
for(int i=0;i<2*n;i++)
{
int x;
cin >> x;
A.push_back(x);
if(x>max)
max = x;
}
vector <int> A1 (max, -1);
for(int i=0;i<=2*n;i+=2)
{
for(int j=A[i];j<A[i+1];j++)
{
A1[j]=1;
}
}
for(int i=0;i<=max;i++)
{
if(A1[i]==1)
ans++;
}
cout << ans;
return 0;
}
```
:::success
掰掰 :D
:::