先将y轴坐标离散化,建树,再将线段横坐标按从小到大排序,从左到右插入,对于同一个矩形的两条对y轴平行的线段,左边的线段标记为-1,右边的线段标记为1,插入时判断y轴上这一段被覆盖的次数,成段更新这部分每太想明白,所以都直接更新到了根子叶,耗时比较长。
#include#include #include int cmp1(const void *a,const void *b); int cmp(const void *a,const void *b); struct node { int high,low; double x; int cover; //cover值存储被覆盖的面积 }stu[10000]; struct kode //存储线段信息 { double x; int y1,y2; int flag; //flag代表是左端还是右端 }line[10000]; struct mode //存储顶点信息,用于离散化中对纵坐标排序及建立映射 { double x,y; int flag; int up; }star[20000]; double ff[2100]; //存储映射 double ans; void build(int low,int high,int x) { stu[x].high=high; stu[x].low=low; stu[x].cover=0; stu[x].x=0; if(high==(low+1)) return ; int mid=(high+low)/2; build(low,mid,2*x); build(mid,high,x*2+1); //对于求两点之间距离这种情况,建树时右儿子左端点不是mid+1,而是mid } void insert(int low,int high,double x,int flag,int n) { if((stu[n].low+1)==stu[n].high) { if(stu[n].cover>1) ans+=(ff[stu[n].high]-ff[stu[n].low])*(x-stu[n].x); stu[n].cover+=flag; stu[n].x=x; return ; } if((stu[n].high==high)&&(stu[n].low==low)) //插入时更新到根子叶 { insert(stu[n*2].low,stu[n*2].high,x,flag,n*2); insert(stu[n*2+1].low,stu[2*n+1].high,x,flag,n*2+1); return ; } if(low>=stu[2*n+1].low) { insert(low,high,x,flag,n*2+1); } else if(high<=stu[2*n].high) { insert(low,high,x,flag,n*2); } else { insert(low,stu[n*2].high,x,flag,n*2); insert(stu[n*2+1].low,high,x,flag,n*2+1); } } int main() { int n,m,i,j,k,max,snum,f=1,t; double temp,x1,x2,y1,y2; scanf("%d",&t); while(t--) { scanf("%d",&n); snum=0; for(i=0;i 0) { line[star[i].up-1].y2=max; //利用顶点中存储的信息,将点还原成线段 line[star[i].up-1].x=star[i].x; line[star[i].up-1].flag=star[i].flag; } else { line[-star[i].up-1].y1=max; line[-star[i].up-1].x=star[i].x; line[-star[i].up-1].flag=star[i].flag; } } build(1,max,1); qsort(line,2*n,sizeof(line[0]),cmp1); //按x左边将线段排序,依次插入 ans=0; for(i=0;i y)>(bb->y)?1:-1); } int cmp1(const void *a,const void *b) { kode *aa=(kode *)a; kode *bb=(kode *)b; return ((aa->x)>(bb->x)?1:-1); }