#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> using namespace std; const int N=210; struct node{ int left,right,c; //c : 区间被覆盖的层数, m: 区间的测度 double m; }tree[N*4]; struct Line{ double x,y1,y2; //纵方向直线, x:直线横坐标, y1 y2:直线上的下面与上面的两个纵坐标 int s; //s = 1 : 直线为矩形的左边, s = 0:直线为矩形的右边 }line[N]; bool cmp(Line a,Line b){ return a.x<b.x; } double ty[N],y[N]; //y[] 整数与浮点数的对应数组; ty[]:用来求y[]的辅助数组 void build(int t,int left,int right){ tree[t].left=left; tree[t].right=right; tree[t].c=0; tree[t].m=0; if(left+1<right){ int mid=(left+right)>>1; build(t<<1,left,mid); build((t<<1)+1,mid,right); } } void update(int t){ if(tree[t].c>0) tree[t].m=y[tree[t].right]-y[tree[t].left]; //将线段树上区间的端点分别映射到 y[]数组所对应的浮点数上,由此计算出测度 else if(tree[t].left+1==tree[t].right) tree[t].m=0; else tree[t].m=tree[t<<1].m+tree[(t<<1)+1].m; } void insert(int t,int left,int right){ if(left<=tree[t].left && tree[t].right<=right){ tree[t].c++; update(t); return ; } int mid=(tree[t].left+tree[t].right)>>1; if(left<mid) insert(t<<1,left,right); if(right>mid) insert((t<<1)+1,left,right); update(t); } void del(int t,int left,int right){ if(left<=tree[t].left && tree[t].right<=right){ tree[t].c--; update(t); return ; } int mid=(tree[t].left+tree[t].right)>>1; if(left<mid) del(t<<1,left,right); if(right>mid) del((t<<1)+1,left,right); update(t); } int getindex(int n,double x){//二分查找出浮点数 t 在数组y[]中的位置(此即所谓的映射关系) int left,right,mid; left=1;right=n; while(left<=right){ mid=(left+right)>>1; if(y[mid]<x) left=mid+1; else right=mid-1; } return left; } int main(){ int n,i; double x1,y1,x2,y2; int cas=1; while(scanf("%d",&n)!=EOF){ if(n==0) break; for(i=0;i<n;i++){ scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[i*2].x=x1; line[i*2].y1=y1; line[i*2].y2=y2; line[i*2].s=1; line[i*2+1].x=x2; line[i*2+1].y1=y1; line[i*2+1].y2=y2; line[i*2+1].s=0; ty[i*2]=y1;ty[i*2+1]=y2; } n<<=1; sort(line,line+n,cmp); sort(ty,ty+n); //默认升序排序 int num=1; y[1]=ty[0]; for(i=1;i<n;i++){ //离散化处理数组 ty[]使之不含重覆元素,得到新的数组存放到数组y[]中 if(ty[i]!=ty[i-1]) y[++num]=ty[i]; } build(1,1,num);//树的叶子节点与数组 y[]中的元素个数相同,以便建立一一对应的关系 int left,right; double ans=0; for(i=0;i<n-1;i++){ left=getindex(num,line[i].y1); //由对应关系计算出线段两端在树中的位置 right=getindex(num,line[i].y2); if(line[i].s==1) //插入矩形的左边 insert(1,left,right); else //删除矩形的右边 del(1,left,right); ans+=tree[1].m*(line[i+1].x-line[i].x); } printf("Test case #%d\n",cas++); printf("Total explored area: %.2lf\n\n",ans); } return 0; }
代码转自:http://www.cnblogs.com/CXCXCXC/p/5003389.html(poj1151)