矩形面积并

#include <iostream>
#include <vector>
#include <algorithm>
#include<cstdio>
using namespace std;
typedef double Type;
#define ll double
#define maxn 200200
// 垂直线段
struct VLine {
    Type x;
    Type y1, y2;
    int val;
    VLine() {}
    VLine(Type _x, Type _y1, Type _y2,int _v) {
        x = _x;
        y1 = _y1;
        y2 = _y2;
        val = _v;
    }
};
vector <VLine> Vl;

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

// 矩形
struct Rectangle {
    Type x0, y0, x1, y1;
    Rectangle() {}
    Rectangle(Type _x0, Type _y0, Type _x1, Type _y1) {
        x0 = _x0; y0 = _y0;
        x1 = _x1; y1 = _y1;
    }
};
vector <Rectangle> Rec;

double tmp[maxn];
int  tmpsize;
double bin[maxn];
int size;

struct Tree {
    int p;
    int l, r;
    int nCover;  // 被完全覆盖的次数
    Type ylen;   // 矩形并测度
    Type yylen;  // 矩形交测度
    void Update1();// 矩形并的向上更新
    void Update2();// 矩形交的向上更新
    int Mid() {
        return (l + r) >> 1;
    }
}T[maxn*4];
void Tree::Update1()
{
        if(nCover > 0) ylen = bin[r] - bin[l];
        else if(l + 1 == r) ylen = 0;
        else ylen = T[p<<1].ylen + T[p<<1|1].ylen;
}
void Tree::Update2()
 {
        if(nCover >=2) yylen = bin[r] - bin[l];
        else if(l + 1 == r) yylen = 0;
        else if(nCover==1) yylen=T[p<<1].ylen+T[p<<1|1].ylen;
        else  yylen=T[p<<1].yylen+T[p<<1|1].yylen;
}
void Build(int p, int l, int r) 
{
    T[p].l = l;T[p].r = r;T[p].p = p;T[p].ylen = T[p].nCover = 0;
    if(l + 1 == r || l == r) return ;
    int mid = (l + r) >> 1;
    Build(p<<1, l, mid);
    Build(p<<1|1, mid, r);
}

void Insert(int p, int l, int r, int val)
{
    if(l <= T[p].l && T[p].r <= r) {
        T[p].nCover += val;
        T[p].Update1(); T[p].Update2();
        return ;
    }
    int mid = T[p].Mid();
    if(l < mid)  Insert(p<<1, l, r, val);
    if(mid < r)  Insert(p<<1|1, l, r, val);
    T[p].Update1(); T[p].Update2();
}

void ProcessBinArray() {
    sort(tmp, tmp +tmpsize);
    bin[size = 1] = tmp[0];
    for(int i = 1; i <tmpsize ;i++) {
        if(tmp[i] != tmp[i-1])
            bin[++size] = tmp[i];
    }
}

int Binary(Type v) {
    int l = 1;
    int r = size;
    while(l <= r) {
        int m = (l + r) >> 1;
        if(bin[m] == v) return m;
        if(v > bin[m]) l = m + 1;
        else r = m - 1;
    }
}

int main() {
    int n;
    int i, j;
    Type x[4], y[4];
    int ca;scanf("%d",&ca);
    while(ca--) {
        scanf("%d", &n);
        Rec.clear();
        Vl.clear();
        tmpsize = 0;

        for(i = 0; i < n; i++) {
            for(j = 0; j < 2; j++) {
                scanf("%lf %lf", &x[j], &y[j]);
                tmp[ tmpsize++ ] = y[j];
            }
            Rec.push_back(Rectangle(x[0], y[0], x[1], y[1]));
        }
        ProcessBinArray();
        for(i = 0; i < Rec.size(); i++) {
            Rectangle& rt = Rec[i];
            if(rt.x0 == rt.x1 || rt.y0 == rt.y1)
                continue;
            int y0 = Binary(rt.y0);
            int y1 = Binary(rt.y1);
            Vl.push_back(VLine(rt.x0, y0, y1, 1));
            Vl.push_back(VLine(rt.x1, y0, y1, -1));
        }
        sort(Vl.begin(), Vl.end(), cmp);
        Build(1, 1, size);

        ll ans = 0;
        for(i = 0; i < Vl.size(); i++) {
            if(i) {
                ans += (ll)(Vl[i].x - Vl[i-1].x) * T[1].yylen;
            }
            Insert(1, Vl[i].y1, Vl[i].y2, Vl[i].val);
        }
        printf("%.2lf\n", ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值