扫描线模板

Posted wans-caesar-02111007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫描线模板相关的知识,希望对你有一定的参考价值。

突然意识到忘记扫描线怎么写叻,赶快补补。

我是离散化了y坐标,将x坐标排序,线段树里面下标是离散后的y,存的是实际的覆盖了的y的长度。

主要是$update$的时候,如果当前整个区间都被覆盖叻,那么直接更新成这段的实际长度。如果已经到叶子节点,长度就是0,剩下是没有被覆盖完的情况,就用左右儿子更新。

查询时只需要$O(1)$取出当前根节点即可,因为存的是当前全局中被覆盖了的y区间,乘上x区间(因为是坐标轴所以左闭右开)即可。

然后离散化和$update$的时候都要左闭右开!!最好记一下套路吧...

#include<bits/stdc++.h>
using namespace std;

int n;
int X1[105], Y1[105], X2[105], Y2[105];

struct TR {
    int X, Y1, Y2, opt;
    TR(int X = 0, int Y1 = 0, int Y2 = 0, int opt = 0) :
        X(X), Y1(Y1), Y2(Y2), opt(opt) { }
} line[505];
bool cmp(TR a, TR b) { return a.X < b.X; }

long long tag[505];
long long tree[505], a[1005];
void push_down(int nd, int l, int r) {
    if(tag[nd])    tree[nd] = a[r + 1] - a[l];//////////////左闭右开
    else if(l == r)    tree[nd] = 0;
    else tree[nd] = tree[nd << 1] + tree[nd << 1 | 1];
}

void add(int nd, int l, int r, int L, int R, int opt) {
    if(l >= L && r <= R) {
        tag[nd] += opt;
        push_down(nd, l, r);
        return ;
    }
    push_down(nd, l, r);
    int mid = (l + r) >> 1;
    if(L <= mid) add(nd << 1, l, mid, L, R, opt);
    if(R > mid)    add(nd << 1 | 1, mid + 1, r, L, R, opt);
    push_down(nd, l, r);
}

int main() {
    freopen("olddriver.in", "r", stdin);
    freopen("olddriver.out", "w", stdout);
    scanf("%d", &n);
    int tot = 0;
    for(int i = 1; i <= n; i ++) {
        scanf("%d%d%d%d", &X1[i], &Y1[i], &X2[i], &Y2[i]);
        a[++tot] = Y1[i];
        line[tot] = TR(X1[i], Y1[i], Y2[i], 1);
        a[++tot] = Y2[i];
        line[tot] = TR(X2[i], Y1[i], Y2[i], -1);
    }
    sort(a + 1, a + 1 + tot);
    sort(line + 1, line + 1 + tot, cmp);
    int m = unique(a + 1, a + 1 + tot) - a - 1;
    long long ans = 0;
    for(int i = 1; i < tot; i ++) {
        int L = lower_bound(a + 1, a + 1 + m, line[i].Y1) - a;
        int R = lower_bound(a + 1, a + 1 + m, line[i].Y2) - a - 1;///////////左闭右开
        add(1, 1, m, L, R, line[i].opt);
        ans += 1ll * tree[1] * (line[i+1].X - line[i].X);
    }
    printf("%lld", ans);
    return 0;
}

 

以上是关于扫描线模板的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段2——.vue文件的模板

VSCode自定义代码片段(vue主模板)

Eclipse 中的通用代码片段或模板

调用模板化成员函数:帮助我理解另一个 *** 帖子中的代码片段

vscode代码片段生成vue模板

xml Eclipse模板(代码片段)检查参数并最终抛出IllegalArgumentException