http://codevs.cn/problem/3044/
线段树扫描线矩形面积求并
基本思路就是将每个矩形的长(平行于x轴的边)投影到线段树上
下边+1,上边-1;
然后根据线段树的权值和与相邻两条边的差值(高度差)求出相应的矩形面积
#includeusing namespace std; const int N = 1100; #define DB double int F[N << 2]; DB W[N << 2], X[N]; struct Node { DB x_1, x_2, h; int how; Node() {}; Node(DB x_1_, DB x_2_, DB h_, int how_) {x_1 = x_1_; x_2 = x_2_; h = h_; how = how_;} }A[N]; bool cmp(Node a, Node b) {return a.h < b.h;} inline int Find(DB num, int n) { int L = 1, R = n, Mid; while(L <= R) { Mid = (L + R) >> 1; if(X[Mid] == num) return Mid; else if(X[Mid] < num) L = Mid + 1; else R = Mid - 1; } } #define lson jd << 1 #define rson jd << 1 | 1 void Pushup(int jd, int l, int r) { if(F[jd]) W[jd] = X[r + 1] - X[l]; else if(l == r) W[jd] = 0; else W[jd] = W[lson] + W[rson]; } void Sec_G(int l, int r, int jd, int x, int y, int yj) { if(x <= l && r <= y) { F[jd] += yj; Pushup(jd, l, r); return ; } int mid = (l + r) >> 1; if(x <= mid) Sec_G(l, mid, lson, x, y, yj); if(y > mid) Sec_G(mid + 1, r, rson, x, y, yj); Pushup(jd, l, r); } int main() { while(1) { int n; cin >> n; int js = 0; if(!n) break; memset(F, 0, sizeof F); memset(W, 0, sizeof W); for(int i = 1; i <= n; i ++) { DB x_1, x_2, y_1, y_2; scanf("%lf%lf%lf%lf", &x_1, &y_1, &x_2, &y_2); A[++ js] = Node(x_1, x_2, y_1, 1); X[js] = x_1; A[++ js] = Node(x_1, x_2, y_2, -1); X[js] = x_2; } sort(X + 1, X + js + 1); sort(A + 1, A + js + 1, cmp); int k = 1; for(int i = 2; i <= js; i ++) if(X[i] != X[i + 1]) X[++ k] = X[i]; DB Answer = 0; for(int i = 1; i < js; i ++) { int l = Find(A[i].x_1, k), r = Find(A[i].x_2, k) - 1; Sec_G(1, k, 1, l, r, A[i].how); Answer += W[1] * (A[i + 1].h - A[i].h); } printf("%.2lf\n", Answer); } return 0; }