覆盖的面积 hdu1255 扫描线+线段树

90 篇文章 0 订阅
12 篇文章 0 订阅

Problem Description


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

Solution


这道题也是类似的,只要在统计的时候看看是否被覆盖两次就可以了。n很大所以艹到底的线段树有点吃力
1A

Code


#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define db double
#define N 4001
using namespace std;
struct treeNode{int l, r, c;}t[N * 5];
struct segement{db x; int l, r, c;}s[N];
struct data{db x; int index;}p[N];
int hy[N];
db lx[N], len;
inline void modify(int now, int l, int r, int v){
    if (t[now].l + 1 == t[now].r){
        t[now].c += v;
        if (t[now].c == 1 && v == -1){
            len -= (lx[r] - lx[l]);
        }else if (t[now].c == 2 && v == 1){
            len += (lx[r] - lx[l]);
        }
        return;
    }else{
        int mid = (t[now].l + t[now].r) >> 1;
        if (r <= mid){
            modify(now * 2, l, r, v);
        }else if (l >= mid){
            modify(now * 2 + 1, l, r, v);
        }else{
            modify(now * 2, l, mid, v);
            modify(now * 2 + 1, mid, r, v);
        }
    }
}
inline void build(int now, int l, int r){
    t[now] = (treeNode){l, r, 0};
    if (l + 1 == r){
        return;
    }
    int mid = (l + r) >> 1;
    build(now * 2, l, mid);
    build(now * 2 + 1, mid, r);
}
inline int cmp1(data a, data b){
    return a.x < b.x;
}
inline int cmp2(segement a, segement b){
    return a.x < b.x;
}
int main(void){
    int T = 0;
    scanf("%d", &T);
    while (T --){
        vector<data> v;
        vector<segement> e;
        int n;
        scanf("%d", &n);
        rep(i, 1, n){
            db u, l, d, r;
            scanf("%lf%lf%lf%lf", &u, &l, &d, &r);
            v.push_back((data){l, i * 2 - 1});
            v.push_back((data){r, i * 2});
            e.push_back((segement){u, i * 2 - 1, i * 2, 1});
            e.push_back((segement){d, i * 2 - 1, i * 2, -1});
        }
        sort(v.begin(), v.end(), cmp1);
        int cnt = 1;
        hy[v[0].index] = cnt;
        lx[1] = v[0].x;
        rep(i, 1, v.size() - 1){
            if (v[i].x != v[i - 1].x){
                cnt += 1;
            }
            hy[v[i].index] = cnt;
            lx[cnt] = v[i].x;
        }
        build(1, 1, cnt);
        rep(i, 0, e.size() - 1){
            e[i].l = hy[e[i].l];
            e[i].r = hy[e[i].r];
        }
        sort(e.begin(), e.end(), cmp2);
        len = 0;
        db tot = 0;
        rep(i, 0, e.size() - 2){
            modify(1, e[i].l, e[i].r, e[i].c);
            tot += (e[i + 1].x - e[i].x) * len;
        }
        printf("%.2f\n", tot);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值