洛谷 P5490【模板】扫描线

洛谷 P5490【模板】扫描线

题目链接
题目描述
n n n 个矩形的面积并。
输入格式
第一行一个正整数 n n n
接下来 n n n 行每行四个非负整数 x 1 , y 1 , x 2 , y 2 x_1, y_1, x_2, y_2 x1,y1,x2,y2,表示一个矩形的左下角坐标为 ( x 1 , y 1 ) (x_1, y_1) (x1,y1),右上角标为 ( x 2 , y 2 ) (x_2, y_2) (x2,y2)
输出格式
一行一个正整数,表示 n n n 个矩形的并集覆盖的总面积。
输入输出样例
输入 #1
2
100 100 200 200
150 150 250 255
输出 #1
18000
说明/提示
对于 20% 的数据, 1 ≤ n ≤ 1000 1≤n≤1000 1n1000
对于 100% 的数据, 1 ≤ n ≤ 1 0 5 , 0 ≤ x 1 < x 2 ≤ 1 0 9 , 0 ≤ y 1 < y 2 ≤ 1 0 9 1≤n≤10^5,0≤x_1<x_2≤10^9,0≤y_1<y_2 ≤10^9 1n1050x1<x21090y1<y2109

AC代码

#include<cstdio>
#include<algorithm>

const int maxn = 2e5 + 5;
int v[maxn];

struct L {
    int x, y1, y2, state;

    bool operator<(const L &oth) const { return x < oth.x; }
} line[maxn];

struct node {   //线段树
    int l, r, cover;
    long long len;
} sgt[maxn << 3];

inline int ls(int k) { return k << 1; }

inline int rs(int k) { return k << 1 | 1; }

inline void push_up(int k) {
    if (sgt[k].cover)sgt[k].len = sgt[k].r - sgt[k].l;
    else sgt[k].len = sgt[ls(k)].len + sgt[rs(k)].len;
}

void build(int l, int r, int k = 1) {
    sgt[k].l = v[l];
    sgt[k].r = v[r];
    if (r - l <= 1)return;
    int m = (l + r) >> 1;
    build(l, m, ls(k));
    build(m, r, rs(k));
}

void modify(int x, int y, int z, int k = 1) {
    int l = sgt[k].l, r = sgt[k].r;
    if (x <= l && r <= y) {
        sgt[k].cover += z;
        push_up(k);
        return;
    }
    if (x < sgt[ls(k)].r) modify(x, y, z, ls(k));
    if (y > sgt[rs(k)].l) modify(x, y, z, rs(k));
    push_up(k);
}

int main() {
    int a, b, c, d, n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d%d", &a, &b, &c, &d);
        v[i] = b, v[n + i] = d;
        line[i] = (L) {a, b, d, 1}, line[n + i] = (L) {c, b, d, -1};
    }
    n <<= 1;
    std::sort(v + 1, v + n + 1);
    std::sort(line + 1, line + n + 1);
    build(1, n);
    long long ans = 0;
    for (int i = 1; i <= n; ++i) {
        ans += sgt[1].len * (line[i].x - line[i - 1].x);
        modify(line[i].y1, line[i].y2, line[i].state);
    }
    printf("%lld\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值