线段树+扫面线 矩阵面积并

扫面线从下往上扫

将横坐标离散化 用线段树来进行区间更新

维护两个值cnt 和对应的有效的边(cnt>0)的长度

当有一个矩阵的下底边扫过的时候 对应的区间cnt+1

否则 对应的区间cnt-1

每次计算cnt > 0的区间长度 不会存在cnt < 0 的区间 因为上边扫描过之前必先扫描下底边

需要注意的是如何处理cnt和 len的关系

1 void push_up(int root, int l, int r)
2 {
3     if (seg[root].flag > 0) seg[root].len = hor[r+1] - hor[l];
4     else if (l == r) seg[root].len = 0;
5     else seg[root].len = seg[lson(root)].len + seg[rson(root)].len;
6 }

这里对len的计算需要依据 flag(cnt)的值 而线段树并不要维护和、最小值之类的东西 不需要懒标记

更多关于矩阵面积并的细节

http://www.cnblogs.com/zhangmingcheng/p/3907072.html

代码君:

  1 #include <bits/stdc++.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <stdio.h>
  5 #define pb push_back
  6 #define fi first
  7 #define se second
  8 #define lson(r) (r<<1)
  9 #define rson(r) ((r<<1)|1)
 10 
 11 using namespace std;
 12 
 13 typedef long long ll;
 14 
 15 const int MAXN = 1e3+7;
 16 const int MAXV = 507;
 17 const int MAXE = 507;
 18 
 19 struct Seg
 20 {
 21     int flag;
 22     double len;
 23 }seg[MAXN << 2];
 24 struct Line
 25 {
 26     double h, px1, px2;
 27     int x1, x2, flag;
 28     Line () {}
 29     Line (double px1, double px2, double h, int flag) : px1(px1), px2(px2), h(h), flag(flag) {}
 30     bool operator < (Line l) const
 31     {
 32         return h < l.h;
 33     }
 34 }line[MAXN]; 
 35 int n;
 36 double hor[MAXN];
 37 void push_up(int root, int l, int r)
 38 {
 39     if (seg[root].flag > 0) seg[root].len = hor[r+1] - hor[l];
 40     else if (l == r) seg[root].len = 0;
 41     else seg[root].len = seg[lson(root)].len + seg[rson(root)].len;
 42 }
 43 void update(int root, int l, int r, int ul, int ur, int addval)
 44 {
 45     if (l > ur || r < ul) return ;
 46     if (l >= ul && r <= ur)
 47     {
 48         seg[root].flag += addval;
 49         push_up(root, l, r);
 50         return ;
 51     }
 52     int mid = (l+r) >> 1;
 53     update(lson(root), l, mid, ul, ur, addval);
 54     update(rson(root), mid+1, r, ul, ur, addval);
 55     push_up(root, l, r);
 56 }
 57 double query()
 58 {
 59     return seg[1].len;
 60 }
 61 int main()
 62 {
 63     //freopen("in.txt", "r", stdin);
 64     int cas = 1;
 65     while (cin >> n)
 66     {
 67         if (!n) break;
 68         memset(line, 0, sizeof(line));
 69         memset(hor, 0, sizeof(hor));
 70         int num = 0;
 71         for (int i = 0; i < n; i++)
 72         {
 73             double x1, x2, y1, y2;
 74             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 75             line[num] = Line(x1, x2, y1, 1);
 76             hor[num++] = x1;
 77             line[num] = Line(x1, x2, y2, -1);
 78             hor[num++] = x2;
 79         }        
 80         sort(line, line+num);
 81         sort(hor, hor+num);
 82         int m = unique(hor, hor+num) - hor;
 83         for (int i = 0; i < num; i++)
 84         {
 85             line[i].x1 = lower_bound(hor, hor+m, line[i].px1) - hor;
 86             line[i].x2 = lower_bound(hor, hor+m, line[i].px2) - hor;
 87         }
 88         double prey = -1;
 89         double ans = 0;
 90         for (int i = 0; i < num; i++)
 91         {
 92             if (prey == -1)
 93             {
 94                 prey = line[i].h;
 95                 update(1, 0, m-2, line[i].x1, line[i].x2-1, line[i].flag);
 96                 continue;
 97             }
 98             double det = line[i].h - prey;
 99             double len = query();
100             update(1, 0, m-2, line[i].x1, line[i].x2-1, line[i].flag);
101             prey = line[i].h;
102             ans += len*det;
103         }
104         printf("Test case #%d\nTotal explored area: %.2f\n\n", cas++, ans);    
105     }
106     return 0;
107 }
View Code

 

posted @ 2018-03-29 15:57  Lorazepam  阅读(184)  评论(0编辑  收藏  举报