参考http://wenku.baidu.com/view/99fef963783e0912a2162adb.html
基本思路,每个扫描线里存一条纵向边,记录矩形的x坐标和y轴覆盖的范围,矩形左边界的flag为1右边界的flag为-1
那么对所有的矩形都这样建边,然后安x左边从小到大排序所有的扫描线,然后计算面积的时候从左到右查看每条扫描线覆盖的
面积,这个过程通过一个线段树优化,每次加入一条扫描线到树中,相应扫描线范围的cover值+flag,然后统计此时有cover值大于0的线段的总长
那么从这些线段到下一个扫描线的之间一定有面积。因为每加入一个矩形的左边界那么所对应的线段范围的cover加一,每加入一个右边界,对应的cover减一,
所以cover>0的线段范围到下一个扫描线之间的范围一定有面积。
如题目那样,加入第一条线10-20 flag=1
10-20=1
加入第二条线15-25.5 flag=1
10-15=1,15-20=2,20-25.5=1
加入第三条10-20 flag=-1
10-15=0,15-20=1,20-25.5=1
加入15-25.5 flag=-1
10-15=0 15-20=0 20-25.5=0
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define L(x) (x<<1)
#define R(x) (x<<1 | 1)
#define MAX 200
using namespace std;
double cy[2*MAX];
class Seg
{
public :
double x,y1,y2;
int f;
Seg(){};
Seg(double a,double b,double c,int d):x(a),y1(b),y2(c),f(d)
{
}
bool operator <(const Seg &b)const
{
return x<b.x;
}
}seg[2*MAX];
struct node
{
int l;
int r;
int cover;
double length;
}a[MAX*3];
void build(int t,int l ,int r)
{
a[t].l=l;
a[t].r=r;
a[t].cover=0;
a[t].length=0;
if(r-l==1)return ;
int mid =(l+r)>>1;
build(L(t),l,mid);
build(R(t),mid,r);
}
void len(int t)
{
if(a[t].cover>0)
a[t].length=cy[a[t].r]-cy[a[t].l];
else
{
if(a[t].r-a[t].l==1)a[t].length=0;
else
a[t].length=a[L(t)].length+a[R(t)].length;
}
}
void update(int t,Seg &s)
{
int tl=a[t].l;
int tr=a[t].r;
if(cy[tl]==s.y1&&cy[tr]==s.y2)
{
a[t].cover+=s.f;
len(t);
return ;
}
int mid=(tl+tr)>>1;
if(s.y2<=cy[mid])
update(L(t),s);
else
if(s.y1>=cy[mid])
update(R(t),s);
else
{
Seg temp=s;
temp.y2=cy[mid];
update(L(t),temp);
temp=s;
temp.y1=cy[mid];
update(R(t),temp);
}
len(t);
}
int main()
{
int n,m;
int i,j;
double x1,x2,y1,y2;
int ca=1;
while(scanf("%d",&n)!=EOF)
{
if(n==0)break;
m=0;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
seg[++m]=Seg(x1,y1,y2,1);
cy[m]=y1;
seg[++m]=Seg(x2,y1,y2,-1);
cy[m]=y2;
}
sort(seg+1,seg+1+m);
sort(cy+1,cy+1+m);
build(1,1,m);
double ary=0;
for(i=1;i<=m-1;i++)
{
update(1,seg[i]);
ary+=a[1].length*(seg[i+1].x-seg[i].x);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",ca,ary);
ca++;
}
}