POJ 1542 矩形面积并

推荐阅读这篇文章

这里仅根据上述文章进行一些补充。主要是注意这里线段树点的意义变成了“边”。比如+-----+-----+,看作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;
}

猜你喜欢

转载自www.cnblogs.com/Rosebud/p/9071648.html