题意是求矩形覆盖2次以上的面积
第一道扫面线题 看了网上一些扫描线的讲解 没怎么看懂 自己试着敲了一下 感觉还行 比较容易懂
关于扫描线的概念就不多说了 直接上题
离散化:对x轴
线段树 :对离散后的x值
扫描线:对与x轴平行的边
注意节点的的子树 应为必须是一个区间 所有最小区间为为1-2 2-3 3-4 4-5 ??????????
#include#include #include #include 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 ; }