扫描线算法

扫描线

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 7;
struct Line {
    int x, yl, yr, state;
    bool operator<(Line &B) { return x < B.x; }
} line[N];
int v[N];
struct Node {
    int l, r, cover;
    long long len;
} sgt[N<<3];//防止访问左右孩子时溢出
inline void pushup(int k) {
    if (sgt[k].cover) sgt[k].len = sgt[k].r - sgt[k].l;
    else sgt[k].len = sgt[k<<1].len + sgt[k<<1|1].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, k<<1), build(m, r, k<<1|1);
}
void modify(int x, int y, int z, int k=1) {
    int l = sgt[k].l, r = sgt[k].r;
    if (x<=l && y>=r) {
        sgt[k].cover += z;
        pushup(k);
        return;
    }
    if (x < sgt[k<<1].r) modify(x, y, z, k<<1);
    if (y > sgt[k<<1|1].l) modify(x, y, z, k<<1|1);
    pushup(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] = {a, b, d, 1}, line[n+i] = {c, b, d, -1};
    }
    sort(v+1, v+(n<<1)+1);
    sort(line+1, line+(n<<1)+1);
    build(1, n<<1);
    unsigned long long ans = 0;
    for (int i = 1; i <= (n<<1); ++i) {
        ans += sgt[1].len * (line[i].x - line[i-1].x);
        modify(line[i].yl, line[i].yr, line[i].state);
    }
    printf("%llu", ans);
}
posted @ 2024-04-13 14:20  飞花阁  阅读(14)  评论(0)    收藏  举报
//雪花飘落效果