此处的讲解更加详细与系统,代码也要好看100倍。
/*
* poj1151 AC
* 线段树+线段扫描+矩形分割
* 计算平面上重叠矩形的总面积的经典问题
*
* 代码又长又丑,完全不能忍了。
*
* 实数坐标需要离散化,并且需要一个简单的hash数组对应
* 分割方式有两种,纵向与横向,此处采用纵向分割。
* 构造线段树时,注意其区间此处取[l,r)更为方便合适。
* 初始化结构数组时,用构造函数。
*
* */
#include<cstdio>
#include<algorithm>
using namespace std;
struct NODE
{
double x1,x2,y;
bool up;
}yy[1000];
int tot;
struct M
{
double x;
int num;
bool fir;
}xx[1000];
int tot1;
double hash[2000];
bool cmpxx(const M &t1,const M &t2)
{
return t1.x<t2.x;
}
bool cmpyy(const NODE &t1,const NODE &t2)
{
return t1.y<t2.y;
}
inline void add(double x1,double x2,double y,int num,int up)
{
yy[++tot].x1 = x1,yy[tot].x2 = x2;
yy[tot].y = y,yy[tot].up = up;
xx[++tot1].x = x1,xx[tot1].num = tot,xx[tot1].fir = true;
xx[++tot1].x = x2,xx[tot1].num = tot,xx[tot1].fir = false;
return;
}
struct TREE
{
double y;
int top,down;
bool up;
}tree[5000];
bool mark[5000];
void pushdown(int x)
{
tree[x<<1].y = tree[x<<1|1].y = tree[x].y;
tree[x<<1].up = tree[x<<1|1].up = tree[x].up;
mark[x<<1] = mark[x<<1|1] = true;
tree[x<<1].top = tree[x].top,tree[x<<1].down = tree[x].down;
tree[x<<1|1].top = tree[x].top,tree[x<<1|1].down = tree[x].down;
mark[x] = false;
}
void build(int l,int r,int x)
{
mark[x] = true,tree[x].y = 0,tree[x].up = true;
tree[x].top = 0,tree[x].down = 0;
if(l==r-1) return;
int mid = (l+r)>>1;
build(l,mid,x<<1);
build(mid,r,x<<1|1);
}
double update(int t,int l,int r,int x)
{
if(l>yy[t].x2 || r-1<yy[t].x1) return 0;
if(yy[t].x1<=l && r-1<=yy[t].x2)
{
if(mark[x])
{
double s = (hash[r]-hash[l])*(yy[t].y-tree[x].y);
if(tree[x].up && !yy[t].up && tree[x].down<=tree[x].top) s = 0;
tree[x].y = yy[t].y,tree[x].up = yy[t].up;
if(tree[x].up) tree[x].top++;
else tree[x].down++;
return s;
}else
{
tree[x].y = yy[t].y;
tree[x].up = yy[t].up;
}
}
int mid = (l+r)>>1;
if(mark[x]) pushdown(x);
double s = update(t,l,mid,x<<1)+update(t,mid,r,x<<1|1);
return s;
}
int main()
{
int n,num = 0;
// FILE *fin = fopen("d.in","r");
while(true)
{
num++;
// fscanf(fin,"%d",&n);
scanf("%d",&n);
if(!n) break;
int i,sum = 0;
double x1,x2,y1,y2;
tot = tot1 = 0;
for(i=1;i<=n;i++)
{
// fscanf(fin,"%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
add(x1,x2,y1,i,false);
add(x1,x2,y2,i,true);
}
sort(xx+1,xx+tot1+1,cmpxx);
xx[0].x = -1;
for(i=1;i<=tot1;i++)
{
if(xx[i].x>xx[i-1].x) sum++;
hash[sum] = xx[i].x;
if(xx[i].fir) yy[xx[i].num].x1 = sum;
else yy[xx[i].num].x2 = sum-1;
}
sort(yy+1,yy+tot+1,cmpyy);
double ans = 0;
build(1,sum,1);
for(i=1;i<=tot;i++)
ans += update(i,1,sum,1);
printf("Test case #%d\n",num);
printf("Total explored area: %.2f\n\n",ans);
}
return 0;
}