http://poj.org/problem?id=1151
几何面积并 离散化
线段树
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<cstring>
#include<set>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int N=105;
struct node
{
int l,r;
double lf,rf,width;
int cover;
}mem[N*6];//线段树 lf rf 分别为边界 cover 为覆盖情况 width 为覆盖8宽度
struct poin
{
double x;
double y1,y2;
int k;
}point[N*2];//拆点 k为-1代表左点 1 代表右点
double Y[N*2];
bool cmp(poin a,poin b)
{
return a.x<b.x;
}
void build(int x,int l,int r)//建树
{
mem[x].l=l;
mem[x].r=r;
mem[x].lf=Y[l];
mem[x].rf=Y[r];
mem[x].cover=mem[x].width=0;
if(l+1==r)
return ;
int mid=(l+r)>>1;
build(x*2,l,mid);
build(x*2+1,mid,r);
}
void find(int x)//更新此处的覆盖宽度
{
if(mem[x].cover>0)
{
mem[x].width=mem[x].rf-mem[x].lf;
return ;
}
if(mem[x].l+1==mem[x].r)
mem[x].width=0;
else
mem[x].width=mem[x*2].width+mem[x*2+1].width;
}
void add(int x,int k)//加入一个点的影响
{
if(mem[x].lf>=point[k].y1&&mem[x].rf<=point[k].y2)//全部覆盖
{
mem[x].cover+=point[k].k;
find(x);
return ;
}
int mid=(mem[x].l+mem[x].r)>>1;
if(Y[mid]<=point[k].y1)//查看 需要怎样往下更新
{
add(x*2+1,k);
}else if(Y[mid]>=point[k].y2)
{
add(x*2,k);
}else
{
add(x*2,k);
add(x*2+1,k);
}
find(x);
}
int main()
{
//freopen("data.txt","r",stdin);
int n;
int T=0;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
++T;
double x1,y1,x2,y2;
int I=0;
for(int i=1;i<=n;++i)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
point[I].x=x1;
point[I].y1=y1;
point[I].y2=y2;
point[I].k=1;
Y[I]=y1;
++I;
point[I].x=x2;
point[I].y1=y1;
point[I].y2=y2;
point[I].k=-1;
Y[I]=y2;
++I;
}
sort(Y,Y+I);
sort(point,point+I,cmp);
build(1,0,I-1);
add(1,0);
double ans=0;
for(int i=1;i<I;++i)
{
//cout<<i<<endl;
ans+=(mem[1].width*(point[i].x-point[i-1].x));//每次用两个x坐标差 × 当前覆盖宽度
//cout<<ans<<endl;
add(1,i);//cout<<"TTT"<<endl;
}
printf("Test case #%d\n",T);
printf("Total explored area: %.2f\n\n",ans);
}
return 0;
}