码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1542 Atlantics 线段树+离散化扫描

时间:2014-12-28 23:24:32      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:

将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描

每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 const int MAX=200+10;
 9 int flag[MAX<<2];//记录某个区间的下底边个数
10 double sum[MAX<<2];//记录某个区间的下底边总长度
11 double x[MAX];//对x进行离散化,否则x为浮点数且很大无法进行线段树
12 
13 struct Seg{//线段
14     double x1,x2,y;
15     int d;
16     Seg(){}
17     Seg(double x1 , double x2 , double y , int d):x1(x1),x2(x2),y(y),d(d){}
18     bool operator<(const Seg &a)const{
19         return y<a.y;
20     }
21 }s[MAX];
22 
23 void updateCur(int n,int left,int right){
24     if(flag[n]) sum[n] = x[right+1] - x[left];//表示该区间整个线段长度可以作为底边
25     else if(left == right) sum[n] = 0;//叶子结点则底边长度为0(区间内线段长度为0)
26     else sum[n] = sum[n<<1] + sum[n<<1|1];
27 }
28 
29 void update(int o , int l , int r , int s , int t , int d){
30     if(s<=l && r<=t){//该区间是当前扫描线段的一部分,则该区间下底边总长以及上下底边个数差更新
31         flag[o] += d;//更新底边相差差个数
32         updateCur(o , l , r);//更新底边长
33         return;
34     }
35     int mid = (l + r)>>1 , ls = o<<1 , rs = o<<1|1;
36     if(mid >= s) update(ls , l , mid , s , t , d);
37     if(mid+1 <= t) update(rs , mid+1 , r , s , t , d);
38     updateCur(o , l , r);
39 }
40 
41 int bin_search(double key , int n){
42     int l = 0 , r = n-1;
43     while(l<=r){
44         int mid = (l+r) >>1;
45         if(x[mid] == key) return mid;
46         if(x[mid] > key) r=mid-1;
47         else l=mid+1;
48     }
49     return -1;
50 }
51 
52 int main()
53 {
54    // freopen("a.in" , "r" , stdin);
55     int n,cas=0;
56     double x1,x2,y1,y2;
57     while(scanf("%d" , &n) , n){
58         int k=0;
59         for(int i=0;i<n;++i){
60             cin>>x1>>y1>>x2>>y2;
61             x[k]=x1;
62             s[k++]=Seg(x1,x2,y1,1);
63             x[k]=x2;
64             s[k++]=Seg(x1,x2,y2,-1);
65         }
66         sort(x,x+k);
67         sort(s,s+k);
68         int t = unique(x , x+k) - x;
69         double ans=0;
70 
71         for(int i=0;i<k;++i){//扫描线段
72             int pos1 = bin_search(s[i].x1 , t);
73             /*
74             这里因为是把它理解成合法线段,所以最右端第 i 个点 , 对应第 i - 1条边
75             同样道理,在updateCur中,计算有效线段长度时 , 需要x[r+1]
76             */
77             int pos2 = bin_search(s[i].x2 , t)-1;
78             update(1 , 0 , t-1 , pos1 , pos2 , s[i].d);//扫描线段时更新底边长度和底边相差个数
79             ans += sum[1]*(s[i+1].y-s[i].y);//新增加面积
80         }
81         printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,ans);
82     }
83     return 0;
84 }

 

HDU 1542 Atlantics 线段树+离散化扫描

标签:

原文地址:http://www.cnblogs.com/CSU3901130321/p/4190695.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!