Scan line segment tree +
And a rectangular area
Written before the rectangular perimeter and
And the same or with a rectangular perimeter, each side of a rectangular cross-out processing and the vertical edge
The whole edge with a vertical plane into a plurality of sections
The length of the maintenance interval is covered by the segment tree
A scan line and then continues to scan from the bottom up, scan lateral edge
When scanning to a lower rectangular section of these sections of the segment tree overwritten, update information
When scanning the upper side of a rectangle, a period covering these sections can be removed
Then only when statistics rectangular perimeter and different answers
The answer is the current difference in height between the entire range covered by the two scan line length *
#include <iostream> #include <algorithm> #include <map> #include <cstdio> #define inf (int)1e9 using namespace std; int n,w,last,tot,k; double c[10000],ans; double s[10000]; map <double,int> id; struct node { double a,b,c,d; }p[5100]; struct tree { int l,r,sum; double len; }sh[100000]; struct edge { int l,r,kind; double num; }a[11000]; bool cmp(edge a,edge b) { return (a.num<b.num || (a.num==b.num && a.kind>b.kind)); } void pushup(int x) { if (sh[x].sum>0) sh[x].len=c[sh[x].r+1]-c[sh[x].l];//完全覆盖 else if (sh[x].l==sh[x].r) sh[x].len=0;//叶子结点 else sh[x].len=sh[x+x].len+sh[x+x+1].len;//一般情况 } void build(int x,int ll,int rr) { sh[x].l=ll; sh[x].r=rr; sh[x].sum=0; sh[x].len=0; if (ll==rr) return; int mid; mid=(ll+rr)>>1; build(x+x,ll,mid); build(x+x+1,mid+1,rr); } void change(int x,int ll,int rr,int v) { if (sh[x].l>=ll && sh[x].r<=rr) { sh[x].sum+=v; pushup(x); return; } int mid; mid=(sh[x].l+sh[x].r)>>1; if (ll<=mid) change(x+x,ll,rr,v); if (rr>mid) change(x+x+1,ll,rr,v); pushup(x); } int main() { while (1) { tot++; scanf("%d",&n); if (n==0) break; for (int i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&p[i].a,&p[i].b,&p[i].c,&p[i].d); k=0; for (int i=1;i<=n;i++) { k++; s[k]=p[i].a; k++; s[k]=p[i].c; } sort(s+1,s+1+k); int m=unique(s+1,s+1+k)-s-1; for (int i=1;i<=m;i++) id[s[i]]=i,c[i]=s[i]; w=0; for (int i=1;i<=n;i++)//处理扫描线 { w++; a[w].l=id[p[i].a];a[w].r=id[p[i].c]; a[w].num=p[i].b;a[w].kind=1; w++; a[w].l=id[p[i].a];a[w].r=id[p[i].c]; a[w].num=p[i].d;a[w].kind=-1; } build(1,0,m+1); sort(a+1,a+1+w,cmp); ans=0; for (int i=1;i<=w;i++) { change(1,a[i].l,a[i].r-1,a[i].kind); if (i==w) break; ans+=(a[i+1].num-a[i].num)*sh[1].len;//统计答案 } printf("Test case #%d\n",tot); printf("Total explored area: %.2f\n\n",ans); } }