题意:
给定 n 个矩形的坐标,求所有矩形所覆盖的面积。
思路:
1. 由于浮点数的存在并且坐标变化范围过大,需要对坐标进行离散化,这里线段树的叶子节点其实是一个区间
2. 线段树每个节点(区间)需要有一个计数,代表的是整个区间是否存在一根或者多根扫描线。注意,这里指的是“整个区间”
3. 如果这个区间的不存在完全覆盖的扫描线,则求其子区间扫描线的并。
#include <iostream> #include <algorithm> using namespace std; #define lhs l, m, rt << 1 #define rhs m + 1, r, rt << 1 | 1 const int maxn = 2010; double sum[maxn << 2]; int cnt[maxn << 2]; double xcord[maxn]; struct Segment { double l, r, h; int flag;
Segment() { }
Segment(double _l, double _r, double _h, int _f) : l(_l), r(_r), h(_h), flag(_f) { } bool operator < (Segment& other) { return h < other.h; } } seg[maxn] ; void PushUp(int l, int r, int rt) { if (cnt[rt] > 0)
sum[rt] = xcord[r+1] - xcord[l]; else if (l == r)
sum[rt] = 0; else
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void Update(int beg, int end, int value, int l, int r, int rt) { if (beg <= l && r <= end) {
cnt[rt] += value;
PushUp(l, r, rt); return ; } int m = (l + r) >> 1; if (beg <= m)
Update(beg, end, value, lhs); if (end > m)
Update(beg, end, value, rhs);
PushUp(l, r, rt); } int BinSearch(double key, double arr[], int size) { int l = 0, r = size - 1; while (l <= r) { int m = (l + r) >> 1; if (arr[m] == key) return m; else if (arr[m] > key)
r = m - 1; else
l = m + 1; } return -1; } int main() { int n, m; int cases = 0; while (~scanf("%d", &n) && n) {
m = 0; for (int i = 0; i < n; ++i) { double a, b, c, d;
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
xcord[m] = a;
seg[m++] = Segment(a, c, b, 1);
xcord[m] = c;
seg[m++] = Segment(a, c, d, -1); }
sort(xcord, xcord + m);
sort(seg, seg + m); int mm = m;
m = 1; for (int i = 1; i < mm; ++i) if (xcord[i] != xcord[i-1])
xcord[m++] = xcord[i];
memset(cnt, 0, sizeof(cnt));
memset(sum, 0, sizeof(sum)); double ret = 0; for (int i = 0; i < mm - 1; ++i) { int l = BinSearch(seg[i].l, xcord, m); int r = BinSearch(seg[i].r, xcord, m) - 1; if (l <= r)
Update(l, r, seg[i].flag, 0, m - 1, 1);
ret += sum[1] * (seg[i+1].h - seg[i].h); }
printf("Test case #%d\nTotal explored area: %.2lf\n\n", ++cases, ret); } return 0; }