CodeVS 3044 矩形面积求并 | 扫描线 + 线段树

题目:CodeVS 3044

将每个矩形拆成两条平行于 x 轴的线段,分别将 x 坐标和 y 坐标排序,将 x 坐标放到 hash 数组里;

按 y 坐标由小到大的顺序扫描,每次二分查找其对应的 x1 和 x2 在数组 hash 中的位置,即离散化后的值;

用线段树维护的是 x 轴(离散化的)上方的线段原长度;

每扫到一条线段,就把它的 flag(+1 或 -1)加入线段树中重新维护总长度;

每次 ans 累加的是这条线段到下条线段的距离 * 当前线段的总长度。

 1 #include <cstdio>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cstring>
 5 
 6 double hash[205], sum[400005]; int tag[400005];
 7 
 8 int read() {
 9     int x = 0, f = 1;
10     char c = getchar();
11     while (!isdigit(c)) {
12         if (c == '-') f = -1;
13         c = getchar();
14     }
15     while (isdigit(c)) {
16         x = (x << 3) + (x << 1) + (c ^ 48);
17         c = getchar();
18     }
19     return x * f;
20 }
21 
22 struct Line {
23     double x1, x2, y; int flag;
24     bool operator < (const Line &rhs) const {
25         return y < rhs.y;
26     }
27 } line[205];
28 
29 int find(double x, int l, int r) {
30     while (l <= r) {
31         int mid = l + ((r - l) >> 1);
32         if (hash[mid] < x) l = mid + 1;
33         else if (hash[mid] == x) return mid;
34         else r = mid - 1;
35     }
36 }
37 
38 void maintain(int cur, int l, int r) {
39     if (tag[cur]) sum[cur] = hash[r + 1] - hash[l];
40     else if (l == r) sum[cur] = 0;
41     else sum[cur] = sum[cur << 1] + sum[cur << 1 | 1];
42 }
43 
44 void update(int cur, int l, int r, int L, int R, int flag) {
45     if (L <= l && r <= R) tag[cur] += flag;
46     else {
47         int mid = l + ((r - l) >> 1);
48         if (L <= mid) update(cur << 1, l, mid, L, R, flag);
49         if (mid < R) update(cur << 1 | 1, mid + 1, r, L, R, flag);
50     }
51     maintain(cur, l, r);
52 }
53 
54 int main() {
55     while (1) {
56         int n = read();
57         if (n == 0) break;
58         memset(sum, 0, sizeof sum);
59         memset(tag, 0, sizeof tag);
60         double x1, y1, x2, y2;
61         for (int i = 1; i <= n; ++ i) {
62             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
63             line[(i << 1) - 1].x1 = line[i << 1].x1 = x1;
64             line[(i << 1) - 1].x2 = line[i << 1].x2 = x2;
65             line[(i << 1) - 1].y = y1, line[i << 1].y = y2;
66             line[(i << 1) - 1].flag = 1, line[i << 1].flag = -1;
67             hash[(i << 1) - 1] = x1, hash[i << 1] = x2;
68         }
69         std::sort(hash + 1, hash + (n << 1) + 1);
70         std::sort(line + 1, line + (n << 1) + 1);
71         double ans = 0; n <<= 1;
72         for (int i = 1; i <= n; ++ i) {
73             int l = find(line[i].x1, 1, n), r = find(line[i].x2, 1, n) - 1;
74             if (l <= r) update(1, 1, n, l, r, line[i].flag);
75             ans += sum[1] * (line[i + 1].y - line[i].y);
76         }
77         printf("%.2lf", ans);
78     }
79     return 0;
80 }

 

posted @ 2018-02-07 15:13  Milky-Way  阅读(363)  评论(0编辑  收藏  举报