HDU 1255 - 覆盖的面积 (线段树 扫描线 面积交)

49 篇文章 0 订阅
11 篇文章 0 订阅

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 3402    Accepted Submission(s): 1663



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


 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N&lt;=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
 

Author
Ignatius.L & weigang Lee
 

Recommend
Ignatius.L

线段树维护x轴上覆盖长度(一次/多次)


样例我输出7.62竟然过了


#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define S64I1(a) scanf(iform1, &(a))
#define P64I1(a) printf(oform1, (a))
#define FOR(i, s, t) for(int (i)=(s); (i)<(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 4000 + 20;
const int maxo = maxn * 4;

struct Seg {
    double l, r, h, d;
    Seg(double ll=0, double rr=0, double hh=0, int dd=-1) : l(ll), r(rr), h(hh), d(dd) {}
};


int n;
int num = 0;
int segNum = 0;
Seg segs[maxn*2];
double X[maxn*4];

int cover[maxo];
double once[maxo];
double more[maxo];

bool cmp(Seg a, Seg b) {
    return a.h < b.h;
}

void pushUp(int o, int L, int R) {
    if(cover[o] > 1) {
        more[o] = once[o] = X[R+1] - X[L];
    } else if(cover[o] == 1) {
        once[o] = X[R+1] - X[L];
        more[o] = once[o<<1] + once[o<<1|1];
    } else if(R == L) {
        once[o] = more[o] = 0;
    } else {
        once[o] = once[o<<1] + once[o<<1|1];
        more[o] = more[o<<1] + more[o<<1|1];
    }
}


int ql, qr, qv;
void update(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        cover[o] += qv;
        pushUp(o, L, R);
        return ;
    }
    int M = L + (R-L) / 2;
    if(ql <= M) update(o<<1, L, M);
    if(M < qr) update(o<<1|1, M+1, R);
    pushUp(o, L, R);
}

int Bin(double x) {
    int l = 0;
    int r = num-1;
    while(l <= r) {
        int m = (r+l)>>1;
        if(fabs(X[m]-x) < eps) return m;
        else if(X[m] < x) l = m+1;
        else r = m-1;
    }
    return -1;
}

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        memset(cover, 0, sizeof(cover));
        memset(once, 0, sizeof(once));
        memset(more, 0, sizeof(more));
        segNum = num = 0;
        for(int i=0; i<n; i++) {
            double x1, y1, x2, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            segs[segNum++] = Seg(x1, x2, y1, 1);
            segs[segNum++] = Seg(x1, x2, y2, -1);
            X[num++] = x1;
            X[num++] = x2;
        }
        sort(X, X+num);
        int tnum = 1;
        for(int i=1; i<num; i++) {
            if(fabs(X[i]-X[i-1]) > eps) X[tnum++] = X[i];
        }
        num = tnum;
        double ans = 0;
        sort(segs, segs+segNum, cmp);
        for(int i=0; i<segNum-1; i++) {
            ql = Bin(segs[i].l);
            qr = Bin(segs[i].r) - 1;
            qv = segs[i].d;
            if(ql <= qr) update(1, 0, num-1);
            ans += more[1] * (segs[i+1].h - segs[i].h);
        }
        printf("%.2lf\n", ans);
    }

    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值