HDU1255 - 覆盖的面积 (扫描线求面积)

Description

给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

思路

和单纯的求面积非常相似,用len来储存被覆盖到两次以上的区间长度。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
#define endl '\n'
typedef long long ll;

const int N = 3000;

struct snode {
    double x, y1, y2;
    int flag;
    
};

bool cmp(const snode &a, const snode &b) {
    return a.x < b.x;
}

struct tnode {
    double sum, l, r, len;
};

tnode st[N << 2];
snode seg[N];
double num[N];
int lazy[N << 2];

void pushup(int rt) {
    if(lazy[rt] > 0) {
        st[rt].sum = st[rt].r - st[rt].l;
        if(lazy[rt] > 1) st[rt].len = st[rt].sum;
        else st[rt].len = st[rt << 1].sum + st[rt << 1 | 1].sum;
    } else {
        st[rt].sum = st[rt << 1].sum + st[rt << 1 | 1].sum;
        st[rt].len = st[rt << 1].len + st[rt << 1 | 1].len;
    }

}

void update(double L, double R, int rt, int flag) {
    if(L == st[rt].l && R == st[rt].r) {
        lazy[rt] += flag;
        pushup(rt);
        return ;
    }
    if(st[rt << 1].r > L) //>而不是>=?不能等于,否则长度为0,会进入死循环。
        update(L, min(R, st[rt << 1].r), rt << 1, flag);
    if(st[rt << 1 | 1].l < R) 
        update(max(L, st[rt << 1 | 1].l), R, rt << 1 | 1, flag);
    pushup(rt);
}

void build(int lef, int rig, int rt) {
    if(rig - lef > 1) { //由于mid公用,所以>1就可以
        int mid = (lef + rig) / 2;
        st[rt].l = num[lef];
        st[rt].r = num[rig];
        build(lef, mid, rt << 1);
        build(mid, rig, rt << 1 | 1); //mid而不是mid+1?因为是线段,头尾需要相连,否则会少值
        pushup(rt);
    } else {
        st[rt].l = num[lef];
        st[rt].r = num[rig];
        st[rt].sum = 0;
        st[rt].len = 0;
    }
}


int main() {
    
    //ios::sync_with_stdio(false);
    int n;
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        if(!n) break;
        for(int i = 0; i < n; i++) {
            double x1, x2, y1, y2;
            scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
            seg[i].x = x1; seg[i].y1 = y1; seg[i].y2 = y2; 
            seg[i].flag = 1;
            seg[i + n].x = x2; seg[i + n].y1 = y1; seg[i + n].y2 = y2; 
            seg[i + n].flag = -1;

            num[i + 1] = y1;
            num[i + 1 + n] = y2;
        }
        sort(num + 1, num + 1 + (2 * n));
        sort(seg, seg + 2 * n, cmp);
        memset(lazy, 0, sizeof lazy);
        build(1, 2 * n, 1);
        double ans = 0;
        update(seg[0].y1, seg[0].y2, 1, seg[0].flag);
        for(int i = 1; i < 2 * n; i++) {
            ans += (seg[i].x - seg[i - 1].x) * st[1].len;
            //cout << st[1].len << endl;
            update(seg[i].y1, seg[i].y2, 1, seg[i].flag);
            //cout << seg[i].x << " " << seg[i].y1 << " " << seg[i].y2 << endl;
        }
        printf("%.2lf\n", ans);
        //printf("Total explored area: %.2lf\n\n", ans);
    }
}
posted @ 2020-04-20 23:41  limil  阅读(99)  评论(0编辑  收藏  举报