#include <stdio.h> #include <string.h> #include <map> #include <vector> #include <math.h> #include <algorithm> using namespace std; const int MAXN = 262144; class SegmentTree { public: struct Node { int cover; double L, R; double clen; void init(int a = 0, double b = 0, double c = 0, double d = 0) { cover = a, L = b, R = c, clen = d; } } nodes[MAXN]; double Y[MAXN]; void pushDown(int k, int l, int r) { } void pushUp(int k, int l, int r) { if (nodes[k].cover > 0) { nodes[k].clen = nodes[k].R - nodes[k].L; } else { if (l == r) nodes[k].clen = 0; else nodes[k].clen = nodes[k<<1].clen + nodes[k<<1|1].clen; } } void build(int k, int l, int r) { nodes[k].init(0, Y[l], Y[r+1], 0); if (l == r) return ; int mid = (l + r)/2; build(k<<1, l, mid); build(k<<1|1, mid+1, r); pushUp(k, l, r); } void addUpdate(int k, int l, int r, int val) { nodes[k].cover += val; if (nodes[k].cover > 0) { nodes[k].clen = nodes[k].R - nodes[k].L; } else { if (l == r) nodes[k].clen = 0; else nodes[k].clen = nodes[k<<1].clen + nodes[k<<1|1].clen; } } void add(int k, int l, int r, int x, int y, int val) { if (x <= l && r <= y) { addUpdate(k, l, r, val); return; } pushDown(k, l, r); int mid = (l + r)/2; if (x <= mid) add(k<<1, l, mid, x, y, val); if (y > mid) add(k<<1|1, mid+1, r, x, y, val); pushUp(k, l, r); } double r_sum; void qinit() { r_sum = 0; } void query(int k, int l, int r, int x, int y) { if (x <= l && r <= y) { r_sum += nodes[k].clen; return ; } pushDown(k, l, r); int mid = (l + r)/2; if (x <= mid) query(k<<1, l, mid, x, y); if (y > mid) query(k<<1|1, mid+1, r, x, y); pushUp(k, l, r); } } tree; struct Event { double x, yl, yr; int val; Event(double a = 0, double b = 0, double c = 0, int d = 0): x(a), yl(b), yr(c), val(d) {} bool operator<(const Event &a) const { return x < a.x; } }; double Lx[32767], Ly[32767], Rx[32767], Ry[32767], K[32767]; int N; double areaCoverAll() { vector<Event> events; vector<double> VY; map<double, int> RY; for (int i = 0; i < N; i++) { double x1, x2, y1, y2; x1 = Lx[i], x2 = Rx[i]; y1 = Ly[i], y2 = Ry[i]; events.push_back(Event(x1, y1, y2, 1)); events.push_back(Event(x2, y1, y2, -1)); VY.push_back(y1), VY.push_back(y2); } sort(events.begin(), events.end()); sort(VY.begin(), VY.end()); VY.resize(unique(VY.begin(), VY.end()) - VY.begin()); for (int i = 0; i < VY.size(); i++) { tree.Y[i] = VY[i]; RY[VY[i]] = i; } tree.build(1, 0, VY.size()-2); double area = 0, prevX = 0; for (int i = 0, j; i < events.size(); ) { if (i > 0) { tree.qinit(); tree.query(1, 0, VY.size()-2, 0, VY.size()-2); area += (events[i].x - prevX) * tree.r_sum; } j = i; while (j < events.size() && events[j].x <= events[i].x) { tree.add(1, 0, VY.size()-2, RY[events[j].yl], RY[events[j].yr] - 1, events[j].val); j++; } prevX = events[i].x; i = j; } return area; } int main() { int testcase, cases = 0; while (scanf("%d", &N) == 1 && N) { for (int i = 0; i < N; i++) scanf("%lf %lf %lf %lf", &Lx[i], &Ly[i], &Rx[i], &Ry[i]); printf("Test case #%d\n", ++cases); printf("Total explored area: %.2f\n", areaCoverAll()); puts(""); } return 0; }
|