给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
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
题解:大神博客有讲解扫描线:https://blog.csdn.net/qq_18661257/article/details/47658191
#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\n", area);//用c++的输出流不对?用c语言的就A了
}
return 0;
}