/*
以前没想到线段树还能这样用,阅读了胡浩大牛的解题报告,这个线段重叠的思想很巧妙,先把一个矩形拆成两条线段,记录每条线段的两个端点及它的高度,并标记此线段是在矩形的上边还是下边,在利用cnt[]数组记录这个x轴的区间段被这样的线段覆盖了几次,那么在这一题来说,覆盖两次以上既是我们要求的解,所以我们在节点上只要保存覆盖一次,和覆盖两次及两次以上的x长度就可以了,最后用所有x轴被覆盖的长度也就是树根的值乘以y轴的区间(也就是两线段的差值),在累加求和就是解了,对于y轴就相当于枚举了,只不过先要对线段的高度排一下序,这样取y轴区间时便于操作;
自己写了一下,代码如下:
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=10000;
struct tree{double n1,n2;} sum[N<<2];
struct seg{
double x1,x2,h,v;
bool operator <(const seg &tem) const
{
return h<tem.h;
}
} line[N];
double cnt[N<<2],X[N];
void Set(int k,double x1,double y1,double x2,double y2)
{
X[k]=x1;
X[k+1]=x2;
line[k].x1=x1;line[k].x2=x2;line[k].h=y1;line[k].v=1;
line[k+1].x1=x1;line[k+1].x2=x2;line[k+1].h=y2;line[k+1].v=-1;
}
void Pushup(int i,int l,int r)
{
if(cnt[i]>=2){sum[i].n2=sum[i].n1=X[r+1]-X[l];}
else if(cnt[i]==1)
{
sum[i].n1=X[r+1]-X[l];
if(l==r)sum[i].n2=0;
else sum[i].n2=sum[i<<1].n1+sum[i<<1|1].n1;
}
else
{
if(l==r)sum[i].n1=sum[i].n2=0;
else
{
sum[i].n1=sum[i<<1].n1+sum[i<<1|1].n1;
sum[i].n2=sum[i<<1].n2+sum[i<<1|1].n2;
}
}
}
void update(int i,int l,int r,int a,int b,int v)
{
if(l==a&&r==b)
{
cnt[i]+=v;
Pushup(i,l,r);
return ;
}
int mid=(l+r)>>1;
if(b<=mid)update(i<<1,l,mid,a,b,v);
else if(b>mid&&a<=mid)
{
update(i<<1,l,mid,a,mid,v);
update(i<<1|1,mid+1,r,mid+1,b,v);
}
else update(i<<1|1,mid+1,r,a,b,v);
Pushup(i,l,r);
}
int Bin(int l,int r,double v)
{
int mid;
while(l<=r)
{
mid=(l+r)>>1;
if(X[mid]==v)return mid;
else if(X[mid]>v) r=mid-1;
else l=mid+1;
}
return -1;
}
int main()
{
int cas,n,k,m,i;
double x1,x2,y1,y2,ans;
scanf("%d",&cas);
while(cas--)
{
m=0;
scanf("%d",&n);
while(n--)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
Set(m,x1,y1,x2,y2);
m+=2;
}
sort(X,X+m);
sort(line,line+m);
for(i=k=1;i<m;i++)
if(X[i-1]<X[i])
X[k++]=X[i];
int l,r;
ans=0;
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for(i=0;i<m-1;i++)
{
l=Bin(0,k-1,line[i].x1);
r=Bin(0,k-1,line[i].x2)-1;
if(l<=r)update(1,0,k-1,l,r,line[i].v);
ans+=sum[1].n2*(line[i+1].h-line[i].h);
}
printf("%.2lf\n",ans);
}
return 0;
}
/*
10
2
0 0 2 2
1 1 3 3
*/