题意:每组数据给出正方形中点坐标及半边长,求矩形面积并;
思路:采用沿垂直方向计算矩形面积并的方法,把面积切成若干垂直条再累加。zoj上能过,但Uva688却一直RE,已经尝试过开大空间了。。。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double epsi=1e-10; const int maxn=40000; struct line{ double x,y1,y2; //x坐标及上下端点y坐标 int s; line(double a=0,double b=0,double c=0,int d=0):x(a),y1(b),y2(c),s(d){} bool operator <(const line &op2) const{ return x<op2.x; //按x坐标递增排序 } }; extern double ly[maxn<<1]; //上下边的y坐标 class Tree{ int cover; //并区间标志 Tree *child[2]; //左右儿子指针 void deliver(){ //调整覆盖 if(cover) //若并区间未结束,则覆盖区间长度为ly[r]-ly[l];否则覆盖区间长度为左右子树的覆盖区间长度之和 len=ly[r]-ly[l]; else len=child[0]->len+child[1]->len; } public: int l,r; double len; //垂直条长度 void setup(int ll,int rr){ l=ll;r=rr; cover=0;len=0; if(ll+1==rr) return; //若区间无法二分,则返回 int mid=(l+r)/2; child[0]=new Tree(),child[1]=new Tree(); child[0]->setup(ll,mid),child[1]->setup(mid,rr);//构造左右子树 } void paint(const int &ll,const int &rr,const int &v){ //往区间为[l,r]的线段树插入边界标志为v的垂直条[ll,rr] if(ll>=r||rr<=l) return; if(ll<=l&&r<=rr){ //若[ll,rr]覆盖[l,r]则调整区间长度len if(cover+=v) len=ly[r]-ly[l]; else{ if(child[0]==NULL) len=0; else len=child[0]->len+child[1]->len; } return; } child[0]->paint(ll,rr,v),child[1]->paint(ll,rr,v);//递归左右子树 deliver();//调整覆盖区间长度 } void del(){ if(child[0]){ //若左子树存在,则递归删除左右子树 child[0]->del(); delete child[0]; child[1]->del(); delete child[1]; } } }; int cas=0; int n,m,tot,ty; //l表的长度为tot,ly表的长度为ty line l[maxn<<1]; //存储垂直条 double ly[maxn<<1]; //存储地图上下边的y坐标 Tree *seg; //线段树指针 int main(){ while(scanf("%d",&n)!=EOF){ if(n==0) break; tot=ty=0; for(int i=0;i<n;i++){ double x,y,r; scanf("%lf%lf%lf",&x,&y,&r); l[tot++]=line(x-r,y-r,y+r,1); l[tot++]=line(x+r,y-r,y+r,-1); ly[ty++]=y-r;ly[ty++]=y+r; } sort(l,l+tot); sort(ly,ly+ty); ty=unique(ly,ly+ty)-ly;//使用unique函数,除去ly[]中的重复元素 double ans=0; seg=new Tree(); seg->setup(0,ty-1); for(int i=0,j;i<tot;i=j){ if(i) ans+=seg->len*(l[i].x-l[i-1].x); j=i; //依次枚举右方的垂直条,取出底边的y坐标在ly中的序号l,顶边的y坐标在ly中的序号r,左右边界标志k,将[l,r,k]插入线段树 while(j<tot&&fabs(l[i].x-l[j].x)<=epsi){ seg->paint(lower_bound(ly,ly+ty,l[j].y1)-ly,lower_bound(ly,ly+ty,l[j].y2)-ly,l[j].s); ++j; } } seg->del(); delete seg; printf("%d %.2f ",++cas,ans); } return 0; }