一個空間中存在若干矩形,且矩形的放置方向一致——(矩形的每條邊必然和X或者Y軸平行)c++
求這些矩形覆蓋的總面積的大小。(存在若干個矩形相互重疊的問題)算法
考慮線段樹能夠logN的時間內作到區間覆蓋,區間設置特殊值。所以應當採用線段樹進行計算。this
考慮使用線段樹維護當前X軸的長度,則面積應當爲:Σlength*hight。其中hight爲當前Y軸長度減去上一個Y軸長度。length爲當前維護的結果。spa
考慮當將矩形切割成兩條形如,x1,x2,y,val的命令,其中x1,x2表明當前上線/下線的長度;y表明當前高度,val取1或-1分別帶至矩形的起始邊和結束邊。code
對於當前應用場景,具備很明顯的特色,及,對於任意一個矩形,都必然將初始邊和結束邊加進線段樹中。則若某給定區間爲a,b時,不存在當a,b邊對應的結束邊還未被加進線段樹時就被清零或部分清零的可能性。blog
所以,對於任意區間,都有顯而易見的兩種狀態:ci
1,明確的知道該區間已經被填滿。——則區間長度爲區間所能表示的上下限之差。it
2,不知道該區間是否被填滿。——則區間長度爲兩個子區間之差。io
對於2狀況有一個子狀態:及當前區間僅僅包含一個元素:(a == b-1) ——我代碼中區間定義爲左閉右開。對於該區間,若無明確的增長指令,則應當認爲區間長度爲0。ast
#include<bits/stdc++.h> using namespace std; #define ll long long const ll MAXN= 1<<19; const ll MAXM = 2333; int t,n,sizeOfMap =0;; class Node { public: int l,r,number; double sum; double lf,rf; }; Node tree[MAXN]; class Command { public: double x1,x2,y; int val; const bool operator < (Command const &c) { return this->y < c.y; } Command(){} Command(double x1,double x2,double y,int v) { this->x1 = x1; this->x2 = x2; this->y = y; this->val = v; } };Command commands[MAXM]; int command_number = 0; void tree_init(int a,int b,int now) { tree[now].l = a; tree[now].r = b; tree[now].number = 0; tree[now].sum = 0; if(a == b-1)return; int mid = (a+b)/2; tree_init(a,mid,now*2); tree_init(mid,b,now*2+1); } double arr[MAXM]; int find_pos(double tar) { return lower_bound(arr,arr+sizeOfMap,tar)-arr; } void update(int a,int b,int now,int key) { int l = tree[now].l; int r = tree[now].r; int mid = (l+r)/2; int num = tree[now].number; int lc = now * 2; int rc = now * 2 + 1; if(l == a && r ==b) { tree[now].number += key; if(tree[now].number == 0) { if(l == r-1)tree[now].sum =0; else tree[now].sum = tree[lc].sum + tree[rc].sum; }else tree[now].sum = arr[r]-arr[l]; return ; } if(a < mid) { update(a,min(b,mid),lc,key); if(b > mid)update(mid,b,rc,key); }else update(a,b,rc,key); if(tree[now].number == 0) { if(l == r-1)tree[now].sum =0; else tree[now].sum = tree[lc].sum + tree[rc].sum; }else tree[now].sum = arr[r]-arr[l]; return ; } int cases = 1; void init() { sizeOfMap = 0; command_number = 0; // cin>>n; for(int i=0;i<n;++i) { // cin>>arr[i]; double a,b,c,d; cin>>a>>b>>c>>d; arr[sizeOfMap++] = a; arr[sizeOfMap++] = b; arr[sizeOfMap++] = c; arr[sizeOfMap++] = d; commands[command_number++]=Command(a,c,b,1); commands[command_number++]=Command(a,c,d,-1); } sort(arr,arr+sizeOfMap); sort(commands,commands+command_number); tree_init(0,sizeOfMap+2,1); double last = 0.0; double ans = 0; for(int i=0;i<command_number;++i) { double line_now = commands[i].y; if(line_now != last) { double hight = line_now - last; ans += hight * tree[1].sum; // cout<<tree[1].sum<<ends<<hight<<"last: "<<last<<ends<<line_now<<endl; last = line_now; } double x1 = commands[i].x1; double x2 = commands[i].x2; int val = commands[i].val; update(find_pos(x1),find_pos(x2),1,val); } // cout<<ans<<endl; printf("Test case #%d\nTotal explored area: %.2f\n\n",cases++,ans); } int main() { // freopen("data_scanner.in","r",stdin); cin.sync_with_stdio(false); // cin>>t; // for(int i=0;i<t;++i) while(cin>>n&&n) { init(); // cout<<tree[1].sum<<endl; } return 0; }