zoukankan      html  css  js  c++  java
  • 【扫描线模板】

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

    我是离散化了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;
    }
    
  • 相关阅读:
    Nginx的编译,和简单的配置问题
    项目课DNS主域名解析服务器(四)
    项目课DHCP服务(三)
    项目课PXE自动装机(二)
    Nginx 详细讲解
    ansible批量管理工具的搭建与简单的操作
    SUID,SGID,SBIT这些到底是什么
    密码截取
    分治和递归的算法实现求数组A[n]中的前k个最大数
    回溯法实现求1n个自然数中r个数的组合
  • 原文地址:https://www.cnblogs.com/NoTimepleasssse/p/9826365.html
Copyright © 2011-2022 走看看