题意是求矩形覆盖2次以上的面积
第一道扫面线题 看了网上一些扫描线的讲解 没怎么看懂 自己试着敲了一下 感觉还行 比较容易懂
关于扫描线的概念就不多说了 直接上题
离散化:对x轴
线段树 :对离散后的x值
扫描线:对与x轴平行的边
注意节点的的子树 应为必须是一个区间 所有最小区间为为1-2 2-3 3-4 4-5 ··········
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; #define LL(x) (x<<1) #define RR(x) ((x<<1)|1) struct node { double y; int x1,x2; int flash; }A[3100]; struct Node { double x; int tt; int ii; }scatter[3100]; int leap[10000];//标记节点 如果==-1说明当前节点表示的区间不是不是一样的值 否则为对应的值 int n; double map[3100];//每个下标对应浮点型x的值 int cmp(Node a,Node b) { return a.x<b.x; } int cmp2(Node a,Node b) { if(a.ii!=b.ii) return a.ii<b.ii; else return a.x<b.x; } int cmp3(node a,node b) { return a.y<b.y; } int update(int L,int R,int left,int right,int mark,int k) { int mid=(L+R)/2; if(L==left&&right==R) { if(leap[mark]>=0) { leap[mark]+=k; } else { update(L,mid,L,mid,LL(mark),k); update(mid,R,mid,R,RR(mark),k); if(leap[LL(mark)]==leap[RR(mark)]) leap[mark]=leap[LL(mark)]; } } else { if(leap[mark]>=0) { leap[LL(mark)]=leap[mark]; leap[RR(mark)]=leap[mark]; } if(right<=mid) { update(L,mid,left,right,LL(mark),k); } else if(left>=mid) { update(mid,R,left,right,RR(mark),k); } else { update(L,mid,left,mid,LL(mark),k); update(mid,R,mid,right,RR(mark),k); } if(leap[LL(mark)]==leap[RR(mark)]) leap[mark]=leap[LL(mark)]; else leap[mark]=-1; } return 0; } double find(int L,int R,int mark) { double dis=0; if(leap[mark]>=2) { dis+=map[R]-map[L]; return dis; } if(leap[mark]>=0) return 0; int mid=(L+R)/2; dis+=find(L,mid,LL(mark))+find(mid,R,RR(mark)); return dis; } int main() { int T,i,j,a,b; double x1,y1,x2,y2; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(A,0,sizeof(A)); memset(map,0,sizeof(map)); for(i=1;i<=2*n;i+=2) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); A[i].y=y1; A[i].flash=1; A[i+1].y=y2; A[i+1].flash=-1; scatter[i].x=x1; scatter[i].ii=i; scatter[i+1].x=x2; scatter[i+1].ii=i; } sort(scatter+1,scatter+2*n+1,cmp);//对x来离散 应为x值为浮点型 不能成为数组下标 double k=-1; int j=0; for(i=1;i<=2*n;i++) { if(scatter[i].x!=k) { k=scatter[i].x; scatter[i].tt=++j; map[j]=scatter[i].x; } else scatter[i].tt=j; } sort(scatter+1,scatter+2*n+1,cmp2); for(i=1;i<=2*n;i+=2) { A[i].x1=scatter[i].tt; A[i].x2=scatter[i+1].tt; A[i+1].x1=scatter[i].tt; A[i+1].x2=scatter[i+1].tt; } sort(A+1,A+2*n+1,cmp3);//把所有与x轴平行的边按对应的y值排序 memset(leap,0,sizeof(leap)); double area=0; a=A[1].x1; b=A[1].x2; update(1,j,a,b,1,1); for(i=2;i<=2*n;i++) { a=A[i].x1; b=A[i].x2; area+=(A[i].y-A[i-1].y)*find(1,j,1); if(A[i].flash==1) update(1,j,A[i].x1,A[i].x2,1,1); else update(1,j,A[i].x1,A[i].x2,1,-1); } printf("%.2lf\n",area); } return 0; }