|
题目链接:http://poj.org/problem?id=1151
/**//* 题意: 给定n(n <= 100)个矩形,求它们的面积并。
解法: 离散化+线段树 或者 离散化+FloodFill
思路: 数据量很小,直接把浮点数离散成整点,然后暴力FloodFill,最后统计 覆盖的块的实际面积。 也可以采用线段树,具体解法如下面这题: http://www.cppblog.com/menjitianya/archive/2011/03/29/142972.html */
#include <iostream> #include <algorithm> #include <vector> #include <cmath> using namespace std;
#define eps 1e-6 #define maxn 100000 // 垂直x轴的线段 struct VLine { double x; double y1, y2; // y1 <= y2 int val; // in or out VLine() {} VLine(double _x, double _y1, double _y2, int _v) { x = _x; y1 = _y1; y2 = _y2; val = _v; } }; vector <VLine> Inc; double tmp[maxn], bin[maxn]; int tmpsize, binsize;
bool cmp(VLine a, VLine b) { return a.x < b.x; }
void preBinaryProcess() { sort(tmp, tmp + tmpsize); binsize = 0; bin[ ++binsize ] = tmp[0]; int i; for(i = 1; i < tmpsize; i++) { if(fabs(tmp[i] - tmp[i-1]) > eps) bin[ ++binsize ] = tmp[i]; } }
int Binary(double val) { int l = 1; int r = binsize; int m; while(l <= r) { m = (l + r) >> 1; if(fabs(val - bin[m]) < eps) return m; if(val > bin[m]) { l = m + 1; }else r = m - 1; }
}
struct Tree { int nCover; // 当前线段被完全覆盖了几次 double yLen; // 测度、相邻扫描线间y方向的有效长度 int l, r; // 线段树该结点管理的区间 int nowIndex; // 当前结点所在的数组下标
void Update() { if(nCover > 0) { yLen = bin[r] - bin[l]; }else { if(l + 1 == r) yLen = 0; else { yLen = T[nowIndex<<1].yLen + T[nowIndex<<1|1].yLen; } } }
int GetMid() { return (l + r) >> 1; } }T[maxn*4];
void Build(int p, int l, int r) { T[p].nCover = T[p].yLen = 0; T[p].l = l; T[p].r = r; T[p].nowIndex = p; if(l == r || l + 1 == r) return ; int mid = (l + r) >> 1; Build(p<<1, l, mid); Build(p<<1|1, mid, r); }
void Insert(int p, int l, int r, int val) {
if(l <= T[p].l && T[p].r <= r) { T[p].nCover += val; T[p].Update(); return ; }
int mid = T[p].GetMid(); if(l < mid) { Insert(p<<1, l, r, val); } if(r > mid) { Insert(p<<1|1, l, r, val); } T[p].Update(); }
int n; int main() { int i; int Case = 1; while(scanf("%d", &n) != EOF && n) { Inc.clear(); tmpsize = binsize = 0; for(i = 0; i < n; i++) { double x1, y1, x2, y2; scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2); Inc.push_back(VLine(x1, y1, y2, 1)); Inc.push_back(VLine(x2, y1, y2, -1)); tmp[ tmpsize++ ] = y1; tmp[ tmpsize++ ] = y2; } sort(Inc.begin(), Inc.end(), cmp); preBinaryProcess(); Build(1, 1, binsize);
double ans = 0; for(i = 0; i < Inc.size(); i++) { int y1 = Binary(Inc[i].y1); int y2 = Binary(Inc[i].y2); if(y1 == y2) continue; if(i) ans += (Inc[i].x - Inc[i-1].x) * T[1].yLen; Insert(1, y1, y2, Inc[i].val); } printf("Test case #%d\nTotal explored area: %.2lf\n\n", Case++, ans); } return 0; }
|