版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/81986041
Time limit 5000 ms
Memory limit 32768 kB
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
题目分析
求多个矩形的面积交
在求面积并的扫描线基础上扩展一下即可
扫描线—学习笔记
记录 结点p对应区间内至少被覆盖一次的长度
记录 结点p对应区间内至少被覆盖两次的长度
求面积并的上推代码为
void pushup(int p,int s,int t)
{
if(cov[p]>0) len[p]=pos[t+1]-pos[s];
else if(s==t) len[p]=0;
else len[p]=len[p<<1]+len[p<<1|1];
}
我们在此基础上扩展
加入
的情况
并在原来三种情况的基础上加入
的更新
void pushup(int p,int s,int t)
{
if(cov[p]>=2) len[0][p]=len[1][p]=pos[t+1]-pos[s];//加入cov[p]>=2的情况
else if(cov[p]==1)
{
len[0][p]=pos[t+1]-pos[s];
if(s==t) len[1][p]=0;//加入len[1][]的更新
else len[1][p]=len[0][p<<1]+len[0][p<<1|1];
}
else if(s==t) len[0][p]=len[1][p]=0;//原来只有len[0][p]=0;
else//cov[p]==0也加入len[1][]的更新
len[0][p]=len[0][p<<1]+len[0][p<<1|1],
len[1][p]=len[1][p<<1]+len[1][p<<1|1];
}
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef double dd;
int read()
{
int x=0,f=1;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
const int maxn=2010;
int t,n;
int tot1,tot2,cnt;
struct node{dd x,y1,y2;int k;}rem[maxn];
bool cmp(node a,node b){return a.x<b.x;}
dd a[maxn],pos[maxn];
dd len[2][maxn<<2],ans;
int cov[maxn<<2];
void init()
{
cnt=tot1=tot2=0; ans=0;
memset(len,0,sizeof(len));
memset(cov,0,sizeof(cov));
}
void pushup(int p,int s,int t)
{
if(cov[p]>=2) len[0][p]=len[1][p]=pos[t+1]-pos[s];
else if(cov[p]==1)
{
len[0][p]=pos[t+1]-pos[s];
if(s==t) len[1][p]=0;
else len[1][p]=len[0][p<<1]+len[0][p<<1|1];
}
else if(s==t) len[0][p]=len[1][p]=0;
else
len[0][p]=len[0][p<<1]+len[0][p<<1|1],
len[1][p]=len[1][p<<1]+len[1][p<<1|1];
}
void update(int ll,int rr,int s,int t,int p,int v)
{
if(ll<=s&&t<=rr){ cov[p]+=v; pushup(p,s,t); return;}
int mid=s+t>>1;
if(ll<=mid) update(ll,rr,s,mid,p<<1,v);
if(rr>mid) update(ll,rr,mid+1,t,p<<1|1,v);
pushup(p,s,t);
}
int main()
{
t=read();
while(t--)
{
n=read(); init();
for(int i=1;i<=n;i++)
{
dd x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[++tot1]=y1; a[++tot1]=y2;
rem[++tot2].x=x1; rem[tot2].y1=y1; rem[tot2].y2=y2; rem[tot2].k=1;
rem[++tot2].x=x2; rem[tot2].y1=y1; rem[tot2].y2=y2; rem[tot2].k=-1;
}
sort(a+1,a+1+tot1);
for(int i=1;i<=tot1;++i)
if(i==1||a[i]!=a[i-1])
pos[++cnt]=a[i];
sort(rem+1,rem+1+tot2,cmp);
for(int i=1;i<tot2;i++)
{
int ll=lower_bound(pos+1,pos+1+cnt,rem[i].y1)-pos;
int rr=lower_bound(pos+1,pos+1+cnt,rem[i].y2)-pos;
update(ll,rr-1,1,cnt,1,rem[i].k);
ans+=len[1][1]*(rem[i+1].x-rem[i].x);
}
printf("%.2lf\n",ans);
}
return 0;
}