POJ 1151 Atlantis 扫描线+线段树
题意:给出数个矩形对角线的顶点,求所有矩形的面积并
思路:线段树维护(或y 取决于使用垂直扫描还是水平扫描)不同底边的长度,同时一个节点所代表的底边有两种FLAG表示上顶还是下底,想得到结果,不断在线段树中插入新的线即可(模拟扫描线)。
/** @Date : 2017-07-19 10:28:39 * @FileName: POJ 1151 线段树+扫描线+面积并.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <utility> #include <vector> #include <map> #include <set> #include <string> #include <stack> #include <queue> #include <math.h> //#include <bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; struct yuu { int l, r; int flag; double ll, rr; double len; }tt[N]; struct line{ double y, x1, x2; int flag; line(){} line(double _x1, double _x2, double _y, int f){ x1 = _x1; x2 = _x2; y = _y; flag = f; } }; line li[N]; int cmp(line a, line b) { return a.y < b.y; } double a[N], b[N]; void pushup(int p) { if(tt[p].flag > 0) { tt[p].len = tt[p].rr - tt[p].ll; return ; } if(tt[p].l == tt[p].r - 1) tt[p].len = 0; else tt[p].len = tt[p << 1].len + tt[p << 1 | 1].len; } void build(int l, int r, int p) { tt[p].l = l; tt[p].r = r; tt[p].len = tt[p].flag = 0; tt[p].ll = a[l]; tt[p].rr = a[r]; if(l == r - 1) return ; int mid = (l + r) >> 1; build(l, mid, p << 1); build(mid, r, p << 1 | 1); } void update(double x1, double x2, int flag, int p) { if(x1 == tt[p].ll && x2 == tt[p].rr) { tt[p].flag += flag; pushup(p); return ; } if(x2 <= tt[p << 1].rr) update(x1, x2, flag, p << 1); else if(x1 >= tt[p << 1 | 1].ll) update(x1, x2, flag, p << 1 | 1); else { update(x1, tt[p << 1].rr, flag, p << 1); update(tt[p << 1 | 1].ll, x2, flag, p << 1 | 1); } pushup(p); } int main() { int n; int T = 0; while(~scanf("%d", &n) && n) { double x1, x2, y1, y2; int cnt = 0; for(int i = 1; i <= 2*n; i+=2) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); li[i] = line(x1, x2, y1, 1); a[i] = x1; li[i + 1] = line(x1, x2, y2, -1); a[i + 1] = x2; } sort(li + 1, li + 2 * n + 1, cmp); sort(a + 1, a + 2 * n + 1); build(1, 2*n, 1); update(li[1].x1, li[1].x2, li[1].flag, 1); double ans = 0; for(int i = 2; i <= 2 * n; i++) { //cout << li[i].x1 << "#" << li[i].x2 << "#" << li[i].y << endl; ans += tt[1].len * (li[i].y - li[i - 1].y); update(li[i].x1, li[i].x2, li[i].flag, 1); //cout << "~"; } printf("Test case #%d\nTotal explored area: %.2f\n\n", ++T, ans); } return 0; }