题意:给N个矩形,会相互重叠,重叠部分只算一次面积,求总面积
把X坐标排序后离散化成0~m标号,每个标号代表一个点及其和下一个点之间的长度,所以m个点有m-1段。按0~m-1标号建线段树
上边赋值为-1,下边赋值为1,这样一段长度非零的时候,说明当前该段长度是被覆盖的,还需要被计算
这里比较难维护的就是区间的有效长度len
比如说有一个结点,范围是0~2,它的标记值是0,不是代表0~2这段都未被覆盖,而是代表0~2未被整体覆盖,所以其下的点0、1、2当前仍可能被覆盖着
为了解决这个问题,我们每次更新一个区间的len值后马上pushup,这样就可以保证区间len一直是正确的。
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"map" #include"set" #include"vector" #define ll long long #define mems(a,b) memset(a,b,sizeof(a)) #define ls pos<<1 #define rs pos<<1|1 using namespace std; const int MAXN = 100500; const int MAXE = 1005; const int INF = 0x3f3f3f3f; struct Node{ int l,r; double len; int w; }node[MAXN<<2]; struct seg{ double l,r,h; int w; seg(){} seg(double a,double b,double c,int d):l(a),r(b),h(c),w(d){} }line[MAXN<<1]; double h[MAXN<<1]; int n,m,p=1; bool cmp(seg a,seg b){ return a.h<b.h; } int get_pos(double x){ int low=0,high=m,mid; while(low<=high){ mid=(low+high)>>1; if(h[mid]==x) return mid; else if(h[mid]>x) high=mid-1; else low=mid+1; } } void pushup(int pos){ if(node[pos].w) node[pos].len=h[node[pos].r+1]-h[node[pos].l]; else if(node[pos].l==node[pos].r) node[pos].len=0; else node[pos].len=node[ls].len+node[rs].len; } void build(int l,int r,int pos){ node[pos].l=l; node[pos].r=r; node[pos].len=0; node[pos].w=0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,ls); build(mid+1,r,rs); } void update(int l,int r,int pos,int w){ if(l<=node[pos].l&&node[pos].r<=r){ node[pos].w+=w; pushup(pos); ///这里是关键- - return ; } int mid=(node[pos].l+node[pos].r)>>1; if(l<=mid) update(l,r,ls,w); if(r>mid) update(l,r,rs,w); pushup(pos); } int main(){ //freopen("in.txt","r",stdin); while(scanf("%d",&n)&&n){ printf("Test case #%d ",p++); for(int i=0;i<2*n;i+=2){ double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[i]=seg(x1,x2,y1,1); line[i+1]=seg(x1,x2,y2,-1); h[i]=x1; h[i+1]=x2; } sort(h,h+2*n); sort(line,line+2*n,cmp); m=0; for(int i=1;i<2*n;i++) if(h[i]!=h[i-1]) h[++m]=h[i]; ///去重 double ans=0; build(0,m-1,1); for(int i=0;i<2*n-1;i++){ int l=get_pos(line[i].l); int r=get_pos(line[i].r)-1; update(l,r,1,line[i].w); ans+=(line[i+1].h-line[i].h)*node[1].len; } printf("Total explored area: %.2lf ",ans); } return 0; }