首页 > 代码库 > HDU1255 覆盖的面积 【扫描线】

HDU1255 覆盖的面积 【扫描线】

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3743    Accepted Submission(s): 1838


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


 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.
 

Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
 

Sample Input
2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
 

Sample Output
7.63 0.00

题意:给定一些矩形的左下角与右上角的坐标,求这些矩形间的重叠次数在2次及以上的地方的面积和。

题解:这题跟POJ1151很像,主要区别在pushUp函数上,每段区间分为一次覆盖和多次覆盖,因此需要分别统计它们的长度,这样才容易求最终面积。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 2002
#define lson l, mid, rt << 1
#define rson mid, r, rt << 1 | 1
using namespace std;

struct Node {
    double y1, y2, onceLen, moreLen;
    int covers;
} T[maxn << 2];
struct Node2 {
    double x, y1, y2;
    int isLeft;
} xNode[maxn];
double yNode[maxn];

bool cmp(Node2 a, Node2 b) {
    return a.x < b.x;
}

void pushUp(int l, int r, int rt) {
    if(T[rt].covers > 1) {
        T[rt].moreLen = T[rt].y2 - T[rt].y1;
        T[rt].onceLen = 0.0;
    } else if(T[rt].covers == 1) {
        if(r - l == 1) {
            T[rt].moreLen = 0.0;
            T[rt].onceLen = T[rt].y2 - T[rt].y1;
            return;
        }
        T[rt].moreLen = T[rt << 1].onceLen + T[rt << 1 | 1].onceLen
                        + T[rt << 1].moreLen + T[rt << 1 | 1].moreLen;
        T[rt].onceLen = T[rt].y2 - T[rt].y1 - T[rt].moreLen;
    } else {
        if(r - l == 1) {
            T[rt].onceLen = T[rt].moreLen = 0.0;
            return;
        }
        T[rt].onceLen = T[rt << 1].onceLen + T[rt << 1 | 1].onceLen;
        T[rt].moreLen = T[rt << 1].moreLen + T[rt << 1 | 1].moreLen;
    }
}

void build(int l, int r, int rt) {
    T[rt].onceLen = T[rt].moreLen = 0.0;
    T[rt].covers = 0;
    T[rt].y1 = yNode[l];
    T[rt].y2 = yNode[r];
    if(r - l == 1) return;
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
}

void update(Node2 x, int l, int r, int rt) {
    if(x.y1 == T[rt].y1 && x.y2 == T[rt].y2) {
        T[rt].covers += x.isLeft;
        pushUp(l, r, rt);
        return;
    }
    int mid = (l + r) >> 1;
    if(x.y2 <= yNode[mid]) update(x, lson);
    else if(x.y1 >= yNode[mid]) update(x, rson);
    else {
        Node2 x1 = x, x2 = x;
        x1.y2 = x2.y1 = yNode[mid];
        update(x1, lson);
        update(x2, rson);
    }
    pushUp(l, r, rt);
}

int main() {
    //freopen("stdin.txt", "r", stdin);
    int n, i, id, t;
    double x1, y1, x2, y2, sum;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        for(i = id = 0; i < n; ++i) {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            yNode[id] = y1;
            xNode[id].x = x1;
            xNode[id].y1 = y1;
            xNode[id].y2 = y2;
            xNode[id++].isLeft = 1;

            yNode[id] = y2;
            xNode[id].x = x2;
            xNode[id].y1 = y1;
            xNode[id].y2 = y2;
            xNode[id++].isLeft = -1;
        }
        sort(yNode, yNode + id);
        build(0, id - 1, 1);
        sort(xNode, xNode + id, cmp);
        for(i = 0, sum = 0.0; i < id - 1; ++i) {
            update(xNode[i], 0, id - 1, 1);
            sum += T[1].moreLen * (xNode[i + 1].x - xNode[i].x);
        }
        printf("%.2lf\n", sum); 
    }
    return 0;
}


HDU1255 覆盖的面积 【扫描线】