给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
![](https://vj.2vjd.cn/d1adc6253c233d9968f03fe1d872f86d?v=1552528927)
Input输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用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
Sample Output
7.63 0.00
#include<bits/stdc++.h> using namespace std; const int maxn=2011; double sum1[maxn<<2],sum2[maxn<<2],area; double x[maxn<<2]; int cnt[maxn<<2]; int t,n,top1,top2; struct node { double l,r,h;//一条边的信息:左端点的横坐标,右端点的横坐标,高度(即纵坐标) int d; //标记:为1代表为一个矩形的下边,-1为上边 bool operator < (const node&a)const//按高度从小到大排序 { return h<a.h; } } line[maxn<<2]; void pushup(int l,int r,int rt) { if(cnt[rt]) sum1[rt]=x[r+1]-x[l]; else if(l==r) //一定要加上~ sum1[rt]=0; else sum1[rt]=sum1[rt*2]+sum1[rt*2+1]; if(cnt[rt]>=2) sum2[rt]=x[r+1]-x[l]; else if(l==r) //这个也一定要加上 sum2[rt]=0; else if(cnt[rt]==1) sum2[rt]=sum1[rt*2]+sum1[rt*2+1]; else if(cnt[rt]==0) sum2[rt]=sum2[rt*2]+sum2[rt*2+1]; } void update(int L,int R,int v,int l,int r,int rt) { if(L<=l&&R>=r) { cnt[rt]+=v; pushup(l,r,rt); return ; } int mid=(l+r)/2; if(L<=mid) update(L,R,v,l,mid,rt*2); if(R>=mid+1) update(L,R,v,mid+1,r,rt*2+1); pushup(l,r,rt); } void Init() { memset(sum1,0,sizeof(sum1)); memset(sum2,0,sizeof(sum2)); memset(cnt,0,sizeof(cnt)); top1=0,top2=0,area=0; } int main() { scanf("%d",&t); while(t--) { Init(); scanf("%d",&n); for(int i=1; i<=n; i++) { double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1, &y1, &x2,&y2); x[++top1]=x1; x[++top1]=x2; line[++top2]=(node) { x1,x2,y1,1 };//记录下边 line[++top2]=(node) { x1,x2,y2,-1 };//记录上边 } sort(x+1,x+1+top1); sort(line+1,line+1+top2); int k=unique(x+1,x+1+top1)-x-1; for(int i=1; i<top2; i++) { int L=lower_bound(x+1,x+1+k,line[i].l)-x; int R=lower_bound(x+1,x+1+k,line[i].r)-x; R--; update(L,R,line[i].d,1,k-1,1); area+=sum2[1]*(line[i+1].h-line[i].h); } printf("%.2lf ", area);//用c++的输出流不对?用c语言的就A了 } return 0; }