BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平線_掃描線
阿新 • • 發佈:2018-05-20
tro str n) mes NPU sample TP printf 向上
2 5 1
9 10 4
6 8 2
4 6 3
BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平線_掃描線
Description
N個矩形塊,交求面積並.
Input
* Line 1: A single integer: N
* Lines 2..N+1: Input line i+1 describes building i with three space-separated integers: A_i, B_i, and H_i
Output
* Line 1: The total area, in square units, of the silhouettes formed by all N buildings
Sample Input
42 5 1
9 10 4
6 8 2
4 6 3
Sample Output
16
裸的掃描線,這裏從左往右掃。
先將x軸向上平移一個單位,避免處理麻煩的區間長度問題。
然後每個矩形拆成兩條豎線,從左往右掃。
需要在線段樹上維護一些點是否存在。
每個節點記錄sum和raw,當sum>0時raw=r-l+1,否則等於兩個兒子的raw之和,每次修改都要pushup一下。
代碼:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 80050 #define maxn 1000000000 struct Line { int y_1,y_2,x,flg; Line() {} Line(int y__1,int y__2,int x_,int flg_) : y_1(y__1),y_2(y__2),x(x_),flg(flg_) {} bool operator < (const Line &u) const { return x<u.x; } }a[N]; int t[N*40],ls[N*40],rs[N*40],cnt,n,raw[N*40],add[N*40]; void pushdown(int l,int r,int &p,int v) { if(!p) p=++cnt; t[p]+=(r-l+1)*v; add[p]+=v; } void pushup(int l,int r,int p) { if(t[p]>0) raw[p]=r-l+1; else if(l==r) raw[p]=0; else raw[p]=raw[ls[p]]+raw[rs[p]]; } void update(int l,int r,int x,int y,int v,int &p) { if(!p) p=++cnt; if(x<=l&&y>=r) { t[p]+=v; pushup(l,r,p); return ; } int mid=(l+r)>>1; if(add[p]) { pushdown(l,mid,ls[p],add[p]); pushdown(mid+1,r,rs[p],add[p]); add[p]=0; } if(x<=mid) update(l,mid,x,y,v,ls[p]); if(y>mid) update(mid+1,r,x,y,v,rs[p]); pushup(l,r,p); } int main() { scanf("%d",&n); int i,x_1,x_2,h,tot=0; for(i=1;i<=n;i++) { scanf("%d%d%d",&x_1,&x_2,&h); a[++tot]=Line(1,h,x_1,1); a[++tot]=Line(1,h,x_2,-1); } sort(a+1,a+tot+1); int root=0; update(1,maxn,a[1].y_1,a[1].y_2,a[1].flg,root); long long ans=0; for(i=2;i<=tot;i++) { ans+=1ll*(a[i].x-a[i-1].x)*raw[1]; update(1,maxn,a[i].y_1,a[i].y_2,a[i].flg,root); } printf("%lld\n",ans); }
BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平線_掃描線