給你一堆平面內的矩形,求他們的面積並(就是覆蓋的面積)node
若是直接每次覆蓋記錄會致使部分面積重複計算,咱們考錄掃描線算法c++
圖是luogu上找的(算法
就這麼張圖吧:數組
從圖中能夠看到會有重複覆蓋的地方ui
若是把它分割一下:spa
而後能夠把問題分到每兩條線之間求面積在加起來,就不會出現算重的狀況3d
因此咱們要順着從下往上(從哪往哪都行)掃描,產生的線就叫掃描線code
$ Q: $ 那麼如何區分是上邊仍是下邊呢?blog
$ A: $ 賦值:把上邊賦值爲 $ -1 $,下邊賦值爲 $ 1 $ ,而後掃的時候記錄一下就行了get
這時候就須要在根據橫座標進行再分了:
把每一個輸入的橫座標記錄下來排個序,而後掃描按區間進行操做就行了
示意圖:
以上操做能夠用線段上維護。
PS.線段樹別忘了開二倍數組
code(模板題 Luogu P5490):
#include<bits/stdc++.h> #define ls(x) x<<1 //左兒子 #define rs(x) x<<1|1 //右兒子 #define int long long //十年oi一場空,不開longlong見祖宗 using namespace std; int read()//快讀 { int x=0,y=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0',c=getchar();} return x*y; } int ch[2000010][2],dat[2000010],cnt,f[2000010],xx[2000010];//ch、dat是線段樹內容,f是記錄每一個縱區間的操做結果(是否在矩形內),cnt是記錄邊的個數 ,xx是因此橫座標(用於分縱區間) struct node//記錄每條線(矩形的上下邊) { int l,r,h,dat;//l是左端點,r是右端點,h是y(縱座標),dat是上下邊(-1上,1下) }e[2000010]; bool cmp(node x,node y)//從下到上枚舉(模擬掃描過程) { return x.h<y.h; } void build(int l,int r,int x) { ch[x][0]=l; ch[x][1]=r;//定義左右區間 dat[x]=0; f[x]=0; if(l==r) return; int mid=l+r>>1; build(l,mid,ls(x)); build(mid+1,r,rs(x)); } void pushup(int x)//修改每個區間的面積和 { if(f[x])//還在矩陣內 dat[x]=xx[ch[x][1]+1]-xx[ch[x][0]];//繼續計算面積 else dat[x]=dat[ls(x)]+dat[rs(x)];//不然正常上傳(pushup操做) } void update(int x,int l,int r,int d) { //一下兩句別忘了套xx,ch[x][1]別忘了+1 if(xx[ch[x][1]+1]<=l||xx[ch[x][0]]>=r)//徹底不相交 return;//直接return if(xx[ch[x][0]]>=l&&xx[ch[x][1]+1]<=r)//徹底包含 { f[x]+=d;//記錄通過的上下邊 pushup(x);//上傳 return; } //其餘狀況爲有相交但不包含 update(ls(x),l,r,d); update(rs(x),l,r,d); pushup(x); } int n,ans;//字面意思 signed main() { n=read(); for(int i=1;i<=n;i++)//輸入 { int x1=read(),y1=read(),x2=read(),y2=read(); e[++cnt].dat=1,e[cnt].l=x1,e[cnt].r=x2,e[cnt].h=y1,xx[cnt]=x1; e[++cnt].dat=-1,e[cnt].l=x1,e[cnt].r=x2,e[cnt].h=y2,xx[cnt]=x2; } sort(xx+1,xx+cnt+1); sort(e+1,e+1+cnt,cmp); int ji=unique(xx+1,xx+cnt+1)-xx-1;//橫座標去重 build(1,cnt-1,1);//建(線段)樹 for(int i=1;i<cnt;i++)//小於cnt不是小於等於 { update(1,e[i].l,e[i].r,e[i].dat); ans+=dat[1]*(e[i+1].h-e[i].h);//整個橫區間的寬度乘高度 } printf("%lld",ans); }
咕咕咕~