覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3841 Accepted Submission(s): 1887
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
题意:计算重复两次以上的面积。
思路:扫描线。tree[o].sum[i]表示节点o所表示的范围内被覆盖次数至少为i的面积有多少,然后向上返回,这样可以降低复杂度。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int l,r,lazy;
double sum[3];
}tree[8010];
struct node2
{
int l,r,f;
double h;
}line[2010];
bool cmp(node2 a,node2 b)
{
return a.h<b.h;
}
double p[2010],sum[2010],x1[1010],y1[1010],x2[1010],y2[1010];
int n,m;
void build(int o,int l,int r)
{
tree[o].l=l;tree[o].r=r;
tree[o].lazy=0;
tree[o].sum[1]=tree[o].sum[2]=0;
tree[o].sum[0]=sum[tree[o].r]-sum[tree[o].l-1];
if(l==r)
return;
int mi=(l+r)/2;
build(o<<1,l,mi);
build(o<<1|1,mi+1,r);
}
void solve(int o)
{
if(tree[o].l==tree[o].r)
{
int i;
for(i=1;i<=min(2,tree[o].lazy);i++)
tree[o].sum[i]=tree[o].sum[0];
for(;i<=2;i++)
tree[o].sum[i]=0;
return;
}
if(tree[o].lazy>=2)
{
tree[o].sum[2]=tree[o].sum[1]=tree[o].sum[0];
}
else if(tree[o].lazy==1)
{
tree[o].sum[2]=tree[o<<1].sum[1]+tree[o<<1|1].sum[1];
tree[o].sum[1]=tree[o].sum[0];
}
else if(tree[o].lazy==0)
{
tree[o].sum[2]=tree[o<<1].sum[2]+tree[o<<1|1].sum[2];
tree[o].sum[1]=tree[o<<1].sum[1]+tree[o<<1|1].sum[1];
}
}
void update(int o,int l,int r,int f)
{
if(tree[o].l==l && tree[o].r==r && tree[o].lazy+f>=0)
{
tree[o].lazy+=f;
solve(o);
return;
}
int mi=(tree[o].l+tree[o].r)/2;
if(r<=mi)
update(o<<1,l,r,f);
else if(l>mi)
update(o<<1|1,l,r,f);
else
{
update(o<<1,l,mi,f);
update(o<<1|1,mi+1,r,f);
}
solve(o);
}
int find(double f)
{
int l=0,r=m,mi;
while(l<r)
{
mi=(l+r)/2;
if(p[mi]<f)
l=mi+1;
else
r=mi;
}
return l;
}
int main()
{
int T,t,i,j,k,l,r;
double ans;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1[i],&y1[i],&x2[i],&y2[i]);
p[i*2-1]=x1[i];
p[i*2]=x2[i];
}
sort(p+1,p+1+n*2);
p[0]=-1;
m=-1;
for(i=1;i<=n*2;i++)
if(p[i]!=p[i-1])
p[++m]=p[i];
for(i=1;i<=m;i++)
sum[i]=sum[i-1]+p[i]-p[i-1];
for(i=1;i<=n;i++)
{
l=find(x1[i])+1;r=find(x2[i]);
line[i*2-1].l=l;line[i*2-1].r=r;line[i*2-1].f=1;line[i*2-1].h=y1[i];
line[i*2].l=l;line[i*2].r=r;line[i*2].f=-1;line[i*2].h=y2[i];
}
sort(line+1,line+1+n*2,cmp);
build(1,1,m);
ans=0;
for(i=1;i<n*2;i++)
{
update(1,line[i].l,line[i].r,line[i].f);
ans+=tree[1].sum[2]*(line[i+1].h-line[i].h);
}
printf("%.2f\n",ans);
}
}