线段树扫描线(1---算矩形的总面积)

http://acm.hdu.edu.cn/showproblem.php?pid=1542

线段树扫描线又是线段树的一种特殊的跑法

先将X坐标离散化 

然后将扫描线按照高度从矮到高进行更新

每次遇到下边的时候就在对应的左区间右区间所对应的cnt值++

每次遇到上边的时候就在对应的左区间右区间所对应的cnt值--

然后在PushUp  如果 cnt>0 那么说明整个区间内的线都是有效的 这个时候只需要计算整个区间的长度

如果cnt == 0 并且 l == r 那么就说明这个区间内是没有有效的线 

如果cnt == 0 并且 l != r 那么这个区间内的有效线段就是下属区间的有效线段之和

至于访问到下面的时候为什么不需要将cnt标记下推 

原因有2个: 1.无论下边的节点是2 还是3 只要这个节点的cnt>0  那么就是整个区间的线段都是有效线段 所以不需要具体到将cnt标记下推来区分左子叶的cnt值是1 右节点的cnt值是2 还是3, 效果都是一样的。

2:因为每一条下边长的扫描线都会有一条完全对应的上变成的扫描线来抵消 所以 这个影响会在后面抵消。

最后每次跑扫描线的时候只需要将 sum[1]*(高度差)累加起来就是答案了。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<iomanip>
 4 #define lson l,m,rt<<1
 5 #define rson m+1,r,rt<<1|1
 6 using namespace std;
 7 const int N = 1e3;
 8 struct Node
 9 {
10     double l, r, h;
11     int d;
12     bool operator < (const Node & x) const
13     {
14         return h < x.h;
15     }
16 }A[N];
17 double X[N], sum[N];
18 int cnt[N];
19 void Build(int l, int r, int rt)
20 {
21     cnt[rt] = 0, sum[rt] = 0.0;
22     if(l == r) return ;
23     int m = l+r >> 1;
24     Build(lson);
25     Build(rson);
26 }
27 void PushUp(int l, int r, int rt)
28 {
29     if(cnt[rt])
30     {
31         sum[rt] = X[r] - X[l-1];
32     }
33     else if(l == r) sum[rt] = 0.0;
34     else sum[rt] = sum[rt<<1] + sum[rt<<1|1];
35 }
36 void Revise(int L, int R, int C, int l, int r, int rt)
37 {
38     if(L <= l && r <= R)
39     {
40         cnt[rt] += C;
41         PushUp(l,r,rt);
42         return ;
43     }
44     int m = l+r >> 1;
45     if(L <= m) Revise(L,R,C,lson);
46     if(m < R) Revise(L,R,C,rson);
47     PushUp(l,r,rt);
48 }
49 void Add(double l, double r, double h, int d, int i)
50 {
51     A[i].l = l; A[i].h = h;
52     A[i].r = r; A[i].d = d;
53 }
54 int main()
55 {
56     ios::sync_with_stdio(false);
57     cin.tie(0);
58     cout.tie(0);
59     int Case = 0, n;
60     while(cin >> n, n)
61     {
62         int k = 0;
63         double x1, y1, x2, y2;
64         for(int i = 1; i <= n; i++)
65         {
66             cin >> x1 >> y1 >> x2 >> y2;
67             Add(x1,x2,y1,1,k);
68             X[k++] = x1;
69             Add(x1,x2,y2,-1,k);
70             X[k++] = x2;
71         }
72         sort(X,X+k);
73         sort(A,A+k);
74         int pos = 1;
75         for(int i = 1; i < k; i++)
76         {
77             if(X[i] != X[i-1])
78                 X[pos++] = X[i];
79         }
80         Build(1,pos,1);
81         double ans = 0;
82         for(int i = 0; i < k-1; i++)
83         {
84             int l = lower_bound(X,X+pos,A[i].l) - X;
85             int r = lower_bound(X,X+pos,A[i].r) - X;
86             Revise(l+1,r,A[i].d,1,pos,1);
87             ans += (A[i+1].h - A[i].h) * sum[1];
88         }
89         cout << "Test case #" << ++Case << endl;
90         cout << "Total explored area: " << fixed
91              << setprecision(2) << ans << endl << endl;
92     }
93     return 0;
94 }

 

posted @ 2018-01-31 14:54  Schenker  阅读(309)  评论(0编辑  收藏  举报