描述
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
Sample Output
7.63
0.00
0.00
题意
如上
题解
离散化,做线段树面积并
然后求并两次的,再开个数组sum2表示并两次的面积
如果col>=2表示rt的面积并了至少2次,sum2[rt]=x[r+1]-x[l]
如果l==r表面是叶子结点,sum2[rt]=0
如果col==1表示rt的面积并了一次, 这时我们看它的左右孩子是否被覆盖过,如果有则说明父区间被覆盖了两次,所以sum2[rt]=sum1[rt<<1]+sum1[rt<<1|1]
如果col==0表示rt的面积没有并,直接sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1]
代码
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 5 using namespace std; 6 7 const int N=2005; 8 int col[N<<2]; 9 double sum1[N<<2],sum2[N<<2],x[N<<2]; 10 struct seg 11 { 12 double l,r,h; 13 int s; 14 seg(){} 15 seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s){} 16 bool operator<(const seg &D){ 17 return h<D.h; 18 } 19 }a[N]; 20 21 void PushUp(int rt,int l,int r) 22 { 23 if(col[rt])sum1[rt]=x[r+1]-x[l]; 24 else if(l==r)sum1[rt]=0; 25 else sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1]; 26 27 if(col[rt]>=2)sum2[rt]=x[r+1]-x[l]; 28 else if(l==r)sum2[rt]=0; 29 else if(col[rt]==1)sum2[rt]=sum1[rt<<1]+sum1[rt<<1|1]; 30 else if(col[rt]==0)sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1]; 31 } 32 void Update(int L,int R,int C,int l,int r,int rt) 33 { 34 if(L<=l&&r<=R) 35 { 36 col[rt]+=C; 37 PushUp(rt,l,r); 38 return; 39 } 40 int mid=(l+r)>>1; 41 if(L<=mid)Update(L,R,C,l,mid,rt<<1); 42 if(R>mid)Update(L,R,C,mid+1,r,rt<<1|1); 43 PushUp(rt,l,r); 44 } 45 int main() 46 { 47 int t; 48 scanf("%d",&t); 49 while(t--) 50 { 51 int n,cnt=0; 52 double x1,x2,y1,y2; 53 scanf("%d",&n); 54 for(int i=1;i<=n;i++) 55 { 56 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); 57 a[++cnt]=seg(x1,x2,y1,1); 58 x[cnt]=x1; 59 a[++cnt]=seg(x1,x2,y2,-1); 60 x[cnt]=x2; 61 } 62 sort(x+1,x+1+cnt); 63 sort(a+1,a+1+cnt); 64 int k=1; 65 for(int i=2;i<=cnt;i++) 66 if(x[i]!=x[i-1]) 67 x[++k]=x[i]; 68 memset(col,0,sizeof(col)); 69 memset(sum1,0,sizeof(sum1)); 70 memset(sum2,0,sizeof(sum2)); 71 double ans=0; 72 for(int i=1;i<cnt;i++) 73 { 74 int l=lower_bound(x+1,x+1+k,a[i].l)-x; 75 int r=lower_bound(x+1,x+1+k,a[i].r)-x-1; 76 Update(l,r,a[i].s,1,k,1); 77 ans+=sum2[1]*(a[i+1].h-a[i].h); 78 } 79 printf("%.2f ",ans); 80 } 81 return 0; 82 }