首页 > 代码库 > hdu--1542&&1255--线段树<扫描线>

hdu--1542&&1255--线段树<扫描线>

所谓扫描线一般按照习惯上 就是说从左到右 或者是 从下到上 

这2题 都是这样的运用 但除此 也还有别的方法可以过

我们将下边标记为1 上边标记为-1  这是自下而上的扫描   如果是从左到右 那么自然是左边为1 右边为-1

这边 当然要进行离散化了。  因为是数据蛮大的浮点数嘛~

这步真的很重要= =

然后注意下 unique去重 或者自己手写for遍历一遍 我就懒的写了

直接Lower_bound就可以了  因为这些数据肯定能找到的嘛

这边 线段树的建树需要注意下  因为我们的叶子结点是 1-2    2-3这样的元线段 所以这边我们建立的不是通常我们所建立的1-1  2-2这样的。

其实我还是没有说到重点 就是对于该节点所表示的区间被覆盖一次 2次及以上 没覆盖 或者到达了叶子节点 我们究竟为什么是采取这些操作~

我们先来讲1542-求出矩形覆盖的所有面积<一个区域被覆盖2次 只计算一次>

艹。。。还是自己画图吧。。

但是有什么 不清楚的可以留言= =    

 

  1 #include <iostream>  2 #include <cstring>  3 #include <algorithm>  4 #include <iomanip>  5 using namespace std;  6   7 int cnt;  8 const int size = 220;  9 struct data 10 { 11     int L , R; 12     double x1 , x2 , y; 13     double sum; 14     int flag; 15     data(){}; 16     data( double u , double v , double w , int p ):x1(u),x2(v),y(w),flag(p){}; 17 }tree[size*4] , mat[size]; 18 double w[size]; 19  20 bool cmp( const data p , const data q ) 21 { 22     return p.y < q.y; 23 } 24  25 void pushUp( int rt ) 26 { 27     if( tree[rt].flag ) 28         tree[rt].sum = w[ tree[rt].R ] - w[ tree[rt].L ]; 29     else if( tree[rt].L+1==tree[rt].R ) 30         tree[rt].sum = 0; 31     else 32         tree[rt].sum =  tree[rt<<1].sum + tree[rt<<1|1].sum; 33 } 34  35 void build( int rt , int L , int R ) 36 { 37     int M = ( L + R ) >> 1; 38     tree[rt].L = L; 39     tree[rt].R = R; 40     tree[rt].sum = 0; 41     tree[rt].flag = 0; 42     if( L+1==R ) 43     { 44         return ; 45     } 46     build( rt<<1 , L , M ); 47     build( rt<<1|1 , M , R ); 48 } 49  50 void update( int rt , int L , int R , int var )//var区别是上边还是下边 51 { 52     int M = ( tree[rt].L + tree[rt].R ) >> 1; 53     if( tree[rt].L == L && tree[rt].R == R ) 54     { 55         tree[rt].flag += var; 56         pushUp( rt ); 57         return ; 58     } 59     if( R<=M ) 60         update( rt<<1 , L , R , var ); 61     else if( L>=M ) 62         update( rt<<1|1 , L , R , var ); 63     else 64     { 65         update( rt<<1 , L , M , var ); 66         update( rt<<1|1 , M , R , var ); 67     } 68     pushUp( rt ); 69 } 70  71 int main() 72 { 73     int Case = 1 , n; 74     double x1 , y1 , x2 , y2; 75     double ans; 76     while( cin >> n && n ) 77     { 78         cnt = 1; 79         for( int i = 0 ; i<n ; i++ ) 80         { 81             cin >> x1 >> y1 >> x2 >> y2; 82             w[cnt] = x1; 83             mat[cnt++] = data( x1 , x2 , y1 , 1 ); 84             w[cnt] = x2; 85             mat[cnt++] = data( x1 , x2 , y2 , -1 ); 86         } 87         sort( w+1 , w+cnt );//离散化x轴坐标  88         sort( mat+1 , mat+cnt , cmp );//按y的高低来排  89         cnt = unique( w+1 , w+cnt ) - w; 90         build( 1 , 1 , cnt-1 ); 91         ans = 0; 92         for( int i = 1 ; i<(n<<1) ; i++ ) 93         { 94             int L = lower_bound( w+1 , w+cnt , mat[i].x1 ) - w; 95             int R = lower_bound( w+1 , w+cnt , mat[i].x2 ) - w;     96             update( 1 , L , R , mat[i].flag ); 97             ans += tree[1].sum * ( mat[i+1].y - mat[i].y ); 98         } 99         cout << "Test case #" << Case++ << endl;100         cout << "Total explored area: ";101         cout << setiosflags(ios::fixed);102         cout << setprecision(2) << ans << endl << endl;103     }104     return 0;105 }
View Code
  1 #include <iostream>  2 #include <cstring>  3 #include <algorithm>  4 #include <iomanip>  5 using namespace std;  6   7 int cnt;  8 const int size = 2200;  9 struct data 10 { 11     int L , R; 12     double x1 , x2 , y; 13     double onceSum; 14     double twiceSum; 15     int flag; 16     data(){}; 17     data( double u , double v , double w , int p ):x1(u),x2(v),y(w),flag(p){}; 18 }tree[size*4] , mat[size]; 19 double w[size]; 20  21 bool cmp( const data p , const data q ) 22 { 23     return p.y < q.y; 24 } 25  26 void push( int rt ) 27 { 28     if( tree[rt].flag ) 29         tree[rt].onceSum = w[ tree[rt].R ] - w[ tree[rt].L ]; 30     else if( tree[rt].L +1 == tree[rt].R ) 31         tree[rt].onceSum = 0; 32     else 33         tree[rt].onceSum = tree[rt<<1].onceSum + tree[rt<<1|1].onceSum; 34 } 35  36 void pushUp( int rt ) 37 { 38     if( tree[rt].flag>=2 ) 39         tree[rt].twiceSum = w[ tree[rt].R ] - w[ tree[rt].L ]; 40     else if( tree[rt].L +1 == tree[rt].R ) 41         tree[rt].twiceSum = 0; 42     else if( tree[rt].flag==1 ) 43         tree[rt].twiceSum = tree[rt<<1].onceSum + tree[rt<<1|1].onceSum; 44     else 45         tree[rt].twiceSum =  tree[rt<<1].twiceSum + tree[rt<<1|1].twiceSum; 46 } 47  48 void build( int rt , int L , int R ) 49 { 50     int M = ( L + R ) >> 1; 51     tree[rt].L = L; 52     tree[rt].R = R; 53     tree[rt].onceSum = tree[rt].twiceSum = 0; 54     tree[rt].flag = 0; 55     if( L+1==R ) 56     { 57         return ; 58     } 59     build( rt<<1 , L , M ); 60     build( rt<<1|1 , M , R ); 61 } 62  63 void update( int rt , int L , int R , int var )//var区别是上边还是下边 64 { 65     int M = ( tree[rt].L + tree[rt].R ) >> 1; 66     if( tree[rt].L == L && tree[rt].R == R ) 67     { 68         tree[rt].flag += var; 69         push( rt ); 70         pushUp( rt ); 71         return ; 72     } 73     if( R<=M ) 74         update( rt<<1 , L , R , var ); 75     else if( L>=M ) 76         update( rt<<1|1 , L , R , var ); 77     else 78     { 79         update( rt<<1 , L , M , var ); 80         update( rt<<1|1 , M , R , var ); 81     } 82     push( rt ); 83     pushUp( rt ); 84 } 85  86 int main() 87 { 88     int n , T; 89     double x1 , y1 , x2 , y2; 90     double ans; 91     while( ~scanf("%d",&T) ) 92     { 93         while( T-- ) 94         { 95             cnt = 1; 96             scanf("%d",&n); 97             for( int i = 0 ; i<n ; i++ ) 98             { 99                 scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);100                 w[cnt] = x1;101                 mat[cnt++] = data( x1 , x2 , y1 , 1 );102                 w[cnt] = x2;103                 mat[cnt++] = data( x1 , x2 , y2 , -1 );104             }105             sort( w+1 , w+cnt );//离散化x轴坐标 106             sort( mat+1 , mat+cnt , cmp );//按y的高低来排 107             cnt = unique( w+1 , w+cnt ) - w;108             build( 1 , 1 , cnt-1 );109             ans = 0;110             for( int i = 1 ; i<(n<<1) ; i++ )111             {112                 int L = lower_bound( w+1 , w+cnt , mat[i].x1 ) - w;113                 int R = lower_bound( w+1 , w+cnt , mat[i].x2 ) - w;    114                 update( 1 , L , R , mat[i].flag );115                 ans += tree[1].twiceSum * ( mat[i+1].y - mat[i].y );116             }117             //cout << setiosflags(ios::fixed);118             //cout << setprecision(2) << ans << endl;119             printf("%.2lf\n",ans);120         }121     }122     return 0;123 }
View Code

 

hdu--1542&&1255--线段树<扫描线>