终于A了。哈哈!!
思路大概就是把:所有的矩形分成横线,竖线。按照y轴排序,那么,此时就有了y轴所有横线的区间。就可以用线段树把所有区间分啊分的。。。
画个图,把一个矩形的左边标记为1,右边标记为-1。用cover值来表示一个区间是否有竖线覆盖。
很容易知道,当cover值是大于0的时候,那么有竖线覆盖此区间。
这时,只需要知道覆盖这段区间的x坐标的值,就可以求出面积了。
然后,更新这段区间的cover值,x坐标的值。
#include <iostream>
#include<cstring>
#include<algorithm>
using namespace std;
double sgTree[205<<2]; //区间面积
double y[205];
double x[205<<2]; //区间相邻左边的x值
int cover[205<<2]; //区间的覆盖值,即此区间有几条竖线还仍然在
struct Line
{
double x;
double y_down,y_up;
int side;
}line[205]; //Line表示竖线的x值与它的y值区间
int cmp(Line a,Line b)
{
return a.x<b.x;
}
void build()
{
memset(sgTree,0,sizeof(sgTree));
memset(cover,0,sizeof(cover));
memset(x,0,sizeof(x));
}
void update(int l,int r,int rt,Line a)
{
if(l+1==r)
{
if(cover[rt]>0) //如果,该区间有竖线覆盖,那么计算面积。
sgTree[rt]+=(y[r]-y[l])*(a.x-x[rt]);
cover[rt]+=a.side; //更新该区间的覆盖值与x坐标
x[rt]=a.x;
return;
}
int mid=(l+r)/2;
if(a.y_up<=y[mid]) update(l,mid,rt*2,a);
else if(a.y_down>=y[mid]) update(mid,r,rt*2+1,a);
else
{
Line b; //把要求的区间分成两段
b.x=a.x;
b.y_down=a.y_down;
b.y_up=y[mid];
b.side=a.side;
update(l,mid,rt*2,b);
b.y_down=y[mid];
b.y_up=a.y_up;
update(mid,r,rt*2+1,b);
}
sgTree[rt]=sgTree[rt*2]+sgTree[rt*2+1];
}
int main()
{
int n;
int t=1;
while(scanf("%d",&n)==1&&n)
{
int k=1;
while(n--)
{
double a,b,c,d;
scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
line[k].x=a;
line[k].y_down=b;
line[k].y_up=d;
line[k].side=1;
y[k++]=b;
line[k].x=c;
line[k].y_down=b;
line[k].y_up=d;
line[k].side=-1;
y[k++]=d;
}
sort(y+1,y+k); //把所有横线排序
sort(line+1,line+k,cmp); //把所有竖线排序
build(); //初始化
for(int i=1;i<k;i++)
update(1,k,1,line[i]);
printf("Test case #%d\nTotal explored area: %.2lf\n\n",t++,sgTree[1]);
}
return 0;
}