#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 100010
struct node
{
double x1,x2,y;
int cover;
node(double x1=0,double x2=0,double y=0,int cover=0):x1(x1),x2(x2),y(y),cover(cover){}
bool friend operator<(node X,node Y) //排序
{
return X.y<Y.y;
}
}p[maxn];
double sum[maxn<<2];
int col[maxn<<2];
double x[maxn<<1];
void up(int rt,int l,int r)
{
if(col[rt])
{
sum[rt]=x[r]-x[l-1]; //通过一个点来表示一段区间 ,整段覆盖住了的话,那么长度为右减左
}
else if(l==r)sum[rt]=0; //如果是叶子节点的话,那么长度自然是0
else sum[rt]=sum[rt<<1]+sum[rt<<1|1]; //如果是非叶子节点的话,那么长度等于左右儿子之和,
}
void build(int L,int R,int rt)
{
col[rt]=0;
if(L==R)
{
sum[rt]=0;
return;
}
int m=(L+R)/2;
build(L,m,rt<<1);
build(m+1,R,rt<<1|1);
up(rt,L,R);
}
void update(int L,int R,int rt,int a,int b,int c)
{
if(a<=L&&b>=R)
{
col[rt]+=c;
up(rt,L,R);
return;
}
int m=(L+R)/2;
if(a<=m)
{
update(L,m,rt<<1,a,b,c);
}
if(b>m)
{
update(m+1,R,rt<<1|1,a,b,c);
}
up(rt,L,R);
}
int main()
{
int n,i,len,L,R,Case;
double x1,x2,y1,y2,S;
Case=1;
while(~scanf("%d",&n)&&n)
{
S=0;
for(i=0;i<n;i++)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
p[2*i]=node(x1,x2,y1,1);
p[2*i+1]=node(x1,x2,y2,-1);
x[2*i]=x1; //将所有x坐标都放在一个数组里,方便离散化
x[2*i+1]=x2;
}
len=unique(x,x+2*n)-x; //离散化第一步,去重的过程
build(1,len,1); //建立树的过程
sort(p,p+2*n); //对纵坐标进行排序
sort(x,x+len); //离散化第二步,排序的过程
for(i=0;i<2*n-1;i++) //实际上只用扫描2*n-1条线
{
L=lower_bound(x,x+len,p[i].x1)-x+1; //离散化第三步,二分法查找,+1是因为一个点代表一段
R=lower_bound(x,x+len,p[i].x2)-x; //找出上下界
update(1,len,1,L,R,p[i].cover);
S+=sum[1]*(p[i+1].y-p[i].y); //sum[1]为当前最大覆盖线段长度
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",Case++,S);
}
return 0;
}
线段树面积并-杭电1542
最新推荐文章于 2020-02-23 11:41:03 发布