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; }