【原题题面】传送门
【题面大意】
给出N个矩形,求矩形的面积并。
【题解思路】
线段树扫描线入门题。
实现的一些细节:
存边的信息用结构体,根据x的大小排序
从每段的y值的开始操作
线段树维护的是段的信息
该段被覆盖了几次
左端点贡献为1(左端点以后的线段都是正贡献),右端点贡献为-1(右端点以后的值都没有贡献1+-1=0)
由于区间修改到哪一段是固定的,所以不需要写push
【code】

#include<bits/stdc++.h> using namespace std; #define File "" #define ll long long inline void file(){ freopen(File".in","r",stdin); freopen(File".out","w",stdout); } const int mxn = 100+3; int n,m,T(0); map<double,int> val; double raw[mxn<<1]; struct T{ int l,r,c; double len; }tr[mxn<<4]; struct P{ double x,y1,y2; int k; bool operator <(const P t) const { return x < t.x; } }p[mxn<<1]; #define ls p<<1 #define rs p<<1|1 inline void B(int p,int l,int r){ tr[p].l = l,tr[p].r = r; tr[p].c = tr[p].len = 0; if(l==r) return; int mid = l+r >>1; B(ls,l,mid),B(rs,mid+1,r);//哈。哈。哈。 } inline void U(int p,int l,int r,int k){ if(l <= tr[p].l && tr[p].r <= r){ tr[p].len = ((tr[p].c += k) ? raw[tr[p].r+1] - raw[tr[p].l] : 0); } if(tr[p].l == tr[p].r) return; int mid = tr[p].l+tr[p].r >>1; if(l <= mid) U(ls,l,r,k); if(r > mid) U(rs,l,r,k); tr[p].len = (tr[p].c ? raw[tr[p].r+1]-raw[tr[p].l] : tr[ls].len+tr[rs].len); } int main(){ // file(); while(++T){ scanf("%d",&n); if(!n) return 0; for(int i = 1; i <= n; ++i){ double x1,y1,x2,y2; scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); int id = i<<1; raw[id-1] = y1,raw[id] = y2; p[id-1].x = x1,p[id-1].y1 = y1,p[id-1].y2 = y2,p[id-1].k = 1; p[id].x = x2,p[id].y1 = y1,p[id].y2 = y2,p[id].k = -1; } n <<= 1; sort(raw + 1,raw + n + 1); int m = unique(raw+1,raw+n+1) - (raw+1); for(int i = 1;i <= m; ++i) val[raw[i]] = i; sort(p + 1,p + n + 1); B(1,1,m-1); double ans = 0; for(int i = 1;i < n; ++i){ int y1 = val[p[i].y1],y2 = val[p[i].y2]-1; U(1,y1,y2,p[i].k); ans += tr[1].len * (p[i+1].x - p[i].x); } printf("Test case #%d ",T); printf("Total explored area: %.2f ",ans); puts(""); } return 0; }