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 }