# 【TIOJ】 1224. Rectangular Coverage Area
## [題目連結](https://tioj.ck.tp.edu.tw/problems/1224)
## **時間複雜度**
* $O(NlogN)$
## **解題想法**
直接扣掉重疊面積好像有點難,又不太容易套二維資料結構,不如把每次覆蓋區域不一樣的地方都切成一條長條型,這樣要計算的東西就是 **覆蓋量 $\times$ 高度**,不過要怎麼維護覆蓋量?
當加入一個矩形的時候,必須要對區間都加一次值(代表多被覆蓋一次),同樣,當一個矩形被掃完的時候,必須要對區間都扣一次值(代表少被覆蓋一次),但是每次我想知道的是有多少非 $0$ 的值(代表覆蓋到的實際面積),
這樣就把原本的問題換成了區間操作的問題。
實作上可以使用線段樹,
由於在線段樹上一個區間可以被拆成 $logN$ 個區間,
所以在每個區間的值就是:
* 如果被蓋到,就是整個區間的長度
* 否則,回傳兩個子區間相加
這樣,總複雜度 $O(NlogN)$
## **完整程式**
值得注意的是這邊用 #define int long long 會掛掉,所以要單獨對答案維護 long long 型態
```cpp=
/* Question : TIOJ 1224. Rectangular Coverage Area */
#include<bits/stdc++.h>
using namespace std;
#define opt ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define priq(type) priority_queue<type, vector<type>, greater<type>>
#define mem(x, value) memset(x, value, sizeof(x));
#define pii pair<int, int>
#define pdd pair<double, double>
#define pb push_back
#define f first
#define s second
#define nL cnt * 2
#define nR cnt * 2 + 1
const auto dir = vector< pair<int, int> > { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
const int MAXN = 1e6 + 50;
const int Mod = 1e9 + 7;
int n, l, r, d, u, res, seg[MAXN*4], lazy[MAXN*4];
vector<tuple<int, int, int, int>> side;
void dealt( int cnt, int L, int R ){
if( lazy[cnt] ) seg[cnt] = R - L + 1;
else if( L != R ) seg[cnt] = seg[nL] + seg[nR];
else seg[cnt] = 0;
}
void update( int L, int R, int ul, int ur, int dt, int cnt ){
if( ul <= L && R <= ur ){
lazy[cnt] += dt;
dealt(cnt, L, R);
return;
}
int M = ( L + R ) / 2;
if (ul <= M) update(L, M, ul, ur, dt, nL);
if (M < ur) update(M+1, R, ul, ur, dt, nR);
dealt(cnt, L, R);
}
signed main(){
opt;
cin >> n;
for( int i = 0 ; i < n ; i++ ){
cin >> l >> r >> d >> u;
side.pb({l, d+1, u, 1});
side.pb({r, d+1, u, -1});
}
sort(side.begin(), side.end());
int pre = 0;
long long ans = 0;
for( auto [pos, d, u, dif] : side ){
if( pos != pre ){
ans += 1LL * ( pos - pre ) * seg[1];
pre = pos;
}
update(1, 1000000, d, u, dif, 1);
}
cout << ans << "\n";
}
```