推荐阅读这篇文章
这里仅根据上述文章进行一些补充。主要是注意这里线段树点的意义变成了“边”。比如+-----+-----+,看作3个点abc和两条边e1和e2,那么线段树中点a代表e1,点b代表e2。那么我们在算cover(想象成染黑)的时候,将(a,b,c)这一段染黑的时候,其实只需要染线段树中的a和b点即可!这里解释了,为什么染[l,r]的时候,实际上染的是[l, r - 1]。
但是,push_up的时候,线段树中的l,r对应实际点的l和r-1,所以要补上个1,这里解释的是为什么if(cover[rt]) seg[rt] = x[r + 1] - x[l];
最终代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define pii pair<int,int> #define ll long long #define mst(a,b) memset(a,b,sizeof(a)) #define rep(i,a,b) for(ll i=(a);i<(b);++i) #define rrep(i,a,b) for(ll i=(b-1);i>=a;--i) const double eps = 1e-8, PI = acos(-1.0f); const int inf = 0x3f3f3f3f, maxN = 2e2 + 50; int N, M, T; // Segment tree #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define lch rt << 1 #define rch rt << 1 | 1 int cover[maxN << 2]; double seg[maxN << 2], x[maxN]; struct Line { double l, r, h; int flag; Line(double a = 0, double b = 0, double c = 0, int d = 1) : l(a), r(b), h(c), flag(d) {} bool operator < (const Line& s2) const { return h < s2.h; } } ln[maxN]; int bSearch(double key, int len, double x[]) { int l = 0, r = len - 1, m; while (l <= r) { m = (l + r) >> 1; if (key == x[m]) return m; else if (key < x[m]) r = m - 1; else l = m + 1; } return -1; } void push_up(int rt, int l, int r) { if (cover[rt]) seg[rt] = x[r + 1] - x[l]; else if (l == r) seg[rt] = 0; else seg[rt] = seg[lch] + seg[rch]; } void update(int L, int R, int f, int l, int r, int rt) { if (L <= l && r <= R) { cover[rt] += f; push_up(rt, l, r); return; } int m = (l + r) >> 1; if (L <= m) update(L, R, f, lson); if (R > m) update(L, R, f, rson); push_up(rt, l, r); } int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif int cas = 1; while (~scanf("%d", &N) && N) { int cnt = 0; double x1, y1, x2, y2; rep(i, 0, N) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); x[cnt] = x1; ln[cnt++] = Line(x1, x2, y1, 1); // 下边 x[cnt] = x2; ln[cnt++] = Line(x1, x2, y2, -1); // 上边 } sort(x, x + cnt); sort(ln, ln + cnt); int ncnt = unique(x, x + cnt) - x; mst(cover, 0); mst(seg, 0); double ans = 0; // 从下到上处理cnt-1条边即可 rep(i, 0, cnt - 1) { int l = bSearch(ln[i].l, ncnt, x); int r = bSearch(ln[i].r, ncnt, x); if (r - 1 >= l) update(l, r - 1, ln[i].flag, 0, ncnt - 1, 1); ans += seg[1] * (ln[i + 1].h - ln[i].h); } printf("Test case #%d\nTotal explored area: %.2lf\n\n", cas++, ans); } return 0; }