daimayuan 矩形面积并

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <array>

using namespace std;

/*
http://oj.daimayuan.top/course/15/problem/688

平面上有n个矩形[Xi,1,Xi,2]×[Yi,1,Yi,2]
,也就是左下角(Xi,1,Yi,1)右上角(Xi,2,Yi,2)的矩形。问面积的并是多少。

输入格式
第一行一个整数n(1≤n≤2×105)。

接下来n行,每行四个整数X1,X2,Y1,Y2(1≤X1≤X2≤109,1≤Y1≤Y2≤109)。

注意:可能会有空矩形。

输出格式
输出一个数表示答案。

样例输入
2
1 4 2 3
2 3 1 4
样例输出
5
*/

const int N = 400010;
struct NODE {
    int l, r;
    //int minv, mincnt;
    int lazy;
    int mincnt, len;
}tr[N*4];
vector<int> ys;
vector<array<int, 4>> seg;
int n, m;

void update(int u) {
    tr[u].mincnt = min(tr[u << 1].mincnt, tr[u << 1 | 1].mincnt);
    if (tr[u << 1].mincnt == tr[u << 1 | 1].mincnt) {
        tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len;
    }
    else if (tr[u << 1].mincnt < tr[u << 1 | 1].mincnt) {
        tr[u].len = tr[u << 1].len;
    }
    else {
        tr[u].len = tr[u << 1|1].len;
    }
}

void build(int u, int l, int r) {
    tr[u] = { l, r, 0, 0, 0 };
    if (l == r) {
        tr[u] = { l, r, 0, 0, ys[l + 1] - ys[l] };
    }
    else {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        update(u);
    }
}

void pushdown(int u) {
    int k = tr[u].lazy;
    if (tr[u].lazy) {
        tr[u<<1].mincnt = tr[u<<1].mincnt + k;
        tr[u<<1].lazy = tr[u<<1].lazy + k;
        tr[u << 1|1].mincnt = tr[u << 1|1].mincnt + k;
        tr[u << 1|1].lazy = tr[u << 1|1].lazy + k;
        tr[u].lazy = 0;
    }
}

void modify(int u, int l, int r, int k) {
    if (l <= tr[u].l && r >= tr[u].r) {
        tr[u].mincnt = tr[u].mincnt + k;
        tr[u].lazy = tr[u].lazy + k;
    }
    else {
        int mid = tr[u].l + tr[u].r >> 1;
        pushdown(u);
        if (l <= mid) modify(u << 1, l, r, k);
        if (r > mid) modify(u << 1 | 1, l, r, k);
        update(u);
    }
}


int main() {
    scanf("%d",&n);
    int idx = 1; 
    ys.push_back(-1);
    seg.push_back({ -1,-1,-1,-1 });
    for (int i = 1; i <= n; i++) {
        int x1, y1, x2, y2; 
        scanf("%d%d%d%d", &x1, &x2, &y1, &y2);
        ys.push_back(y1); ys.push_back(y2);
        seg.push_back({ x1,1,y1,y2 });
        seg.push_back({ x2,-1,y1,y2 });
    }

    sort(ys.begin(), ys.end());
    sort(seg.begin(), seg.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    m = ys.size() - 2;

    build(1, 1, m);

    long long ans = 0;
    int totalLen = tr[1].len;
    int prex = 0;
    for (int i = 1; i < seg.size(); i++) {
        int cov = totalLen;
        if (tr[1].mincnt == 0) {
            cov = totalLen - tr[1].len;
        }
        ans += 1ll * (seg[i][0] - prex) * cov;
        prex = seg[i][0];
        int y1 = lower_bound(ys.begin(), ys.end(), seg[i][2]) - ys.begin() ;
        int y2 = lower_bound(ys.begin(), ys.end(), seg[i][3]) - ys.begin() -1;
        modify(1, y1, y2, seg[i][1]);
    }

    printf("%lld\n", ans);


    return 0;
}

posted on 2024-06-12 15:01  itdef  阅读(20)  评论(0)    收藏  举报

导航