Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
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
Sample Output
7.63 0.00
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define debug(x) printf("%d***\n",x)
#define ls(o) (o<<1)
#define rs(o) (o<<1|1)
typedef long long ll;
using namespace std;
const int maxn=1010;
struct SEG{
double l,r,h;
int tag;
SEG(){ }
SEG(double _l,double _r,double _h,int _tag){
l=_l,r=_r,h=_h,tag=_tag;
}
bool operator<(const SEG& b)const{
return h<b.h;
}
}seg[maxn<<1];
double X[maxn<<1];
struct Tree{
int l,r;
double sum1,sum2;//sum1表示当前区间遍历大于等于一次的长度,sum2表示当前区间大于等于两次的长度
int cnt;
}tree[maxn<<3];
/*
利用sum1 来保存大于等于一次的长度,我们每次只更新对应的最高区间,也就是能不往下去就不往下去
然后利用sum2=ls(o).sum1+rs(o).sum1;//当前区间是一次,所以只要下面的一次就够了
*/
void build(int l,int r,int o){
tree[o].l=l,tree[o].r=r;
tree[o].cnt=0;
if(l==r){
tree[o].sum1=tree[o].sum2=0.0;
return ;
}
int mid=(l+r)>>1;
build(l,mid,ls(o));
build(mid+1,r,rs(o));
tree[o].sum1=tree[ls(o)].sum1+tree[rs(o)].sum1;
tree[o].sum2=tree[ls(o)].sum2+tree[rs(o)].sum2;
}
void pushup(int o){//!!!
if(tree[o].cnt>=2){
tree[o].sum2=tree[o].sum1=X[tree[o].r+1]-X[tree[o].l];
}
else if(tree[o].cnt==1){
tree[o].sum1=X[tree[o].r+1]-X[tree[o].l];
if(tree[o].l==tree[o].r) tree[o].sum2=0.0;
else tree[o].sum2=tree[ls(o)].sum1+tree[rs(o)].sum1;
}
else {
if(tree[o].l==tree[o].r)
tree[o].sum1=tree[o].sum2=0.0;
else{
tree[o].sum1=tree[ls(o)].sum1+tree[rs(o)].sum1;
tree[o].sum2=tree[ls(o)].sum2+tree[rs(o)].sum2;
}
}
}
void update(int l,int r,int v,int o){
//printf("l:%d r:%d o:%d\n",l,r,o);
if(l<=tree[o].l&&tree[o].r<=r){
tree[o].cnt+=v;
pushup(o);
return;
}
int mid=(tree[o].l+tree[o].r)>>1;
if(r<=mid)
update(l,r,v,ls(o));
else if(l>mid)
update(l,r,v,rs(o));
else{
update(l,mid,v,ls(o));
update(mid+1,r,v,rs(o));
}
pushup(o);
}
int main(){
//freopen("123.txt","r",stdin);
//freopen("456.txt","w",stdout);
int q,T;
scanf("%d",&T);
while(T--){
scanf("%d",&q);
int n=0,m=0;
for(int i=1;i<=q;i++){
double x1,y1,x2,y2;
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
X[++n]=x1;
seg[++m]=(SEG){x1,x2,y1,1};
X[++n]=x2;
seg[++m]=(SEG){x1,x2,y2,-1};
}
sort(seg+1,seg+m+1);
//去重
sort(X+1,X+n+1);
int k=1;
for(int i=2;i<=n;i++){
if(X[i]!=X[i-1])
X[++k]=X[i];
}
build(1,k-1,1);
double ans=0.0;
for(int i=1;i<m;i++){
int l=lower_bound(X+1,X+k+1,seg[i].l)-X;
int r=lower_bound(X+1,X+k+1,seg[i].r)-X;
update(l,r-1,seg[i].tag,1);
ans+=tree[1].sum2*(seg[i+1].h-seg[i].h);
// printf("ans:%.2f ll:%.2f rr:%.2f h1:%.2f h2:%.2f l:%d r:%d sum:%.2f\n",ans,seg[i].l,seg[i].r,seg[i].h,seg[i+1].h,l,r-1,tree[1].sum2);
}
printf("%.2f\n",ans);
}
return 0;
}