• 线段树 扫描线 L


    学习博客推荐——线段树+扫描线(有关扫描线的理解)

     我觉得要注意的几点

    1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1]

    2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个push_down

    3 注意push_up 写法有点不一样,不过是可以改成一样的。

    简单裸题*2

    L - Atlantis  HDU - 1542 

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn = 220;
    double v[maxn];
    struct node {
        double l, r, h;
        int d;
        node(double l = 0, double r = 0, double h = 0, int d = 0) :l(l), r(r), h(h), d(d) {}
    }line[maxn];
    bool cmp(node a, node b) {
        return a.h < b.h;
    }
    double sum[maxn * 8];
    int lazy[maxn * 4];
    void build(int id, int l, int r) {
        sum[id] = 0;
        lazy[id] = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
    }
    
    void push_up(int id, int l, int r) {
        if (lazy[id]) sum[id] = v[r + 1] - v[l];
        else sum[id] = sum[id << 1] + sum[id << 1 | 1];
    }
    
    void update(int id, int l, int r, int x, int y, int d) {
        if (x <= l && y >= r) {
            lazy[id] += d;
            push_up(id, l, r);
            return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid) update(id << 1, l, mid, x, y, d);
        if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d);
        push_up(id, l, r);
    }
    
    int main() {
        int n, cas = 0;
        while (scanf("%d", &n) != EOF && n) {
            int cnt = 0, tot = 0;
            for (int i = 1; i <= n; i++) {
                double x1, y1, x2, y2;
                scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
                v[++cnt] = x1, v[++cnt] = x2;
                line[++tot] = node(x1, x2, y1, 1), line[++tot] = node(x1, x2, y2, -1);
            }
            sort(v + 1, v + 1 + cnt);
            sort(line + 1, line + 1 + tot, cmp);
            int len = unique(v + 1, v + 1 + cnt) - v - 1;
            double ans = 0;
            build(1, 1, len - 1);
            for (int i = 1; i < tot; i++)//这里注意只需要要tot-1即可,因为我们每次都是按底算的
            {
                int l = lower_bound(v + 1, v + 1 + len, line[i].l) - v;
                int r = lower_bound(v + 1, v + 1 + len, line[i].r) - v - 1;
                update(1, 1, len - 1, l, r, line[i].d);
                ans += sum[1] * (line[i + 1].h - line[i].h);
            }
            printf("Test case #%d
    ", ++cas);
            printf("Total explored area: %.2lf
    
    ", ans);
        }
        return 0;
    }
    View Code
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 8e4 + 10;
    ll v[maxn];
    struct node {
        ll l, r, h;
        int d;
        node(ll l = 0, ll r = 0, ll h = 0, int d = 0) :l(l), r(r), h(h), d(d) {}
    }line[maxn];
    bool cmp(node a, node b) {
        return a.h < b.h;
    }
    ll sum[maxn * 8];
    int lazy[maxn * 4];
    void build(int id, int l, int r) {
        sum[id] = 0;
        lazy[id] = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
    }
    
    void push_up(int id, int l, int r) {
        if (lazy[id]) sum[id] = v[r + 1] - v[l];
        else sum[id] = sum[id << 1] + sum[id << 1 | 1];
    }
    
    void update(int id, int l, int r, int x, int y, int d) {
        if (y<l || x>r) return;
        // printf("id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
        if (x <= l && y >= r) {
            lazy[id] += d;
            if (lazy[id]) sum[id] = v[r + 1] - v[l];
            else sum[id] = sum[id << 1] + sum[id << 1 | 1];
            return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid) update(id << 1, l, mid, x, y, d);
        if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d);
        push_up(id, l, r);
    }
    
    int main() {
        int n, cnt = 0, tot = 0;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            ll l, r, h;
            scanf("%lld%lld%lld", &l, &r, &h);
            v[++cnt] = l, v[++cnt] = r;
            line[++tot] = node(l, r, 0, 1), line[++tot] = node(l, r, h, -1);
        }
        sort(v + 1, v + 1 + cnt);
        sort(line + 1, line + 1 + tot, cmp);
        int len = unique(v + 1, v + 1 + cnt) - v - 1;
        build(1, 1, len - 1);
        ll ans = 0;
        for (int i = 1; i < tot; i++) {
            int l = lower_bound(v + 1, v + 1 + len, line[i].l) - v;
            int r = lower_bound(v + 1, v + 1 + len, line[i].r) - v - 1;
            // printf("l=%d r=%d
    ", l, r);
            update(1, 1, len - 1, l, r, line[i].d);
            ans += sum[1] * (line[i + 1].h - line[i].h);
            // printf("%lld %lld ans=%lld %lld sum=%lld
    ", line[i].l, line[i].r, ans, line[i].h, sum[1]);
            // printf("%lld %lld ans=%lld %lld
    ", line[i + 1].l, line[i + 1].r, ans, line[i + 1].h);
            // printf("
    
    ");
        }
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
    然后就是一个没有这么简单的裸题,比较暴力。
    这个是给每一个y轴都建一棵线段树,每一个y轴代表 y[L]~y[L+1]

    然后每次对于这个矩形的每一个y轴的这一段都查一下,然后如果已经被覆盖了,就删去这一段,然后更新这一段。

    这个题目其实还是很好写的,但是要注意push_down的写法。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int maxn = 440;
    struct rect
    {
        int x1, y1, x2, y2, col;
        rect(int x1=0,int y1=0,int x2=0,int y2=0,int col=0):x1(x1),y1(y1),x2(x2),y2(y2),col(col){}
    }ex[maxn];
    
    int vx[maxn * 2], vy[maxn * 2], color[maxn];
    int sum[maxn][maxn * 8], lazy[maxn][maxn * 8];
    
    void build(int i,int id,int l,int r)
    {
        sum[i][id] = lazy[i][id] = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build( i,id << 1, l, mid);
        build(i, id << 1 | 1, mid + 1, r);
    }
    
    void push_up(int i,int id)
    {
        sum[i][id] = sum[i][id << 1] + sum[i][id << 1 | 1];
        // printf("sum[%d][%d]=%d
    ", i, id, sum[i][id]);
    }
    
    void push_down(int i,int id,int l,int r)
    {
        if (lazy[i][id] == 0) return;
        int mid = (l + r) >> 1;
        sum[i][id << 1] = vx[mid + 1] - vx[l];
        sum[i][id << 1 | 1] = vx[r + 1] - vx[mid + 1];
        lazy[i][id << 1] = lazy[i][id << 1 | 1] = lazy[i][id];
        // printf("l=%d r=%d mid=%d
    ", l, r, mid);
        // printf("x sum[%d][%d]=%d
    ", i, id<<1, sum[i][id<<1]);
        // printf("x sum[%d][%d]=%d
    ", i, id<<1|1, sum[i][id<<1|1]);
        lazy[i][id] = 0;
    }
    
    void update(int i,int id,int l,int r,int x,int y)
    {
        if (x <= l && y >= r) {
            sum[i][id] = vx[r + 1] - vx[l];
            // printf("l=%d r=%d
    ", l, r);
            // printf("ww sum[%d][%d]=%d
    ", i, id, sum[i][id]);
            lazy[i][id] = 1;
            return;
        }
        int mid = (l + r) >> 1;
        push_down(i, id, l, r);
        if (x <= mid) update(i, id << 1, l, mid, x, y);
        if (y > mid) update(i, id << 1 | 1, mid + 1, r, x, y);
        push_up(i, id);
    }
    
    int query(int i,int id,int l,int r,int x,int y)
    {
        if (x <= l && y >= r) return sum[i][id];
        int mid = (l + r) >> 1, ans = 0;
        push_down(i, id, l, r);
        if (x <= mid) ans += query(i, id << 1, l, mid, x, y);
        if (y > mid) ans += query(i, id << 1 | 1, mid + 1, r, x, y);
        return ans;
    }
    
    int main()
    {
        int w, h, n, cas = 0;
        while (scanf("%d%d", &w, &h) && (w + h)) {
            memset(color, 0, sizeof(color));
            int tot = 0, cnt = 0;
            scanf("%d", &n);
            vx[++tot] = 0, vx[++tot] = w;
            vy[++cnt] = 0, vy[++cnt] = h;
            for (int i = 1; i <= n; i++) {
                int x1, y1, x2, y2, col;
                scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &col);
                ex[i] = rect(x1, y1, x2, y2, col);
                vx[++tot] = x1, vx[++tot] = x2;
                vy[++cnt] = y1, vy[++cnt] = y2;
            }
            sort(vx + 1, vx + 1 + tot);
            sort(vy + 1, vy + 1 + cnt);
            int lenx = unique(vx + 1, vx + 1 + tot) - vx - 1;
            int leny = unique(vy + 1, vy + 1 + cnt) - vy - 1;
            // for (int i = 1; i <= lenx; i++) printf("vx[%d]=%d
    ", i, vx[i]);
            for (int i = 1; i < leny; i++) build(i, 1, 1, lenx - 1);
            for (int i = n; i >= 1; i--) {
                // printf("i=%d
    ", i);
                int col = ex[i].col;
                int ans = (ex[i].x2 - ex[i].x1)*(ex[i].y2 - ex[i].y1);
                int lx = lower_bound(vx + 1, vx + 1 + lenx, ex[i].x1) - vx;
                int ly = lower_bound(vy + 1, vy + 1 + leny, ex[i].y1) - vy;
                int rx = lower_bound(vx + 1, vx + 1 + lenx, ex[i].x2) - vx - 1;
                int ry = lower_bound(vy + 1, vy + 1 + leny, ex[i].y2) - vy - 1;
                for (int j = ly; j <= ry; j++) {
                    int res = query(j, 1, 1, lenx - 1, lx, rx);
                    ans -= (vy[j + 1] - vy[j])*res;
                    // printf("j=%d
    ", j);
                    // printf("lx=%d ly=%d rx=%d  ry=%d
    ", lx, ly, rx, ry);
                    // printf("x1=%d y1=%d x2=%d y2=%d
    ", ex[i].x1, ex[i].y1, ex[i].x2, ex[i].y2);
                    // printf("res=%d %d ans=%d
    ", res, vy[j + 1] - vy[j],ans);
                    update(j, 1, 1, lenx - 1, lx, rx);
                }
                color[col] += ans;
                // printf("color[%d]=%d
    ", col, color[col]);
                // printf("
    ");
            }
            int num = 0;
            if (cas) printf("
    ");
            printf("Case %d:
    ", ++cas);
            for (int i = 1; i <= 100; i++) {
                if (color[i]) {
                    printf("%d %d
    ", i, color[i]);
                    num++;
                }
            }
            if (num == 1) printf("There is %d color left on the wall.
    ", num);
            else printf("There are %d colors left on the wall.
    ", num);
        }
        return 0;
    }
    /*
    10 8
    4
    1 9 5 10 9
    1 8 2 9 8
    7 1 10 8 4
    6 2 9 6 4
    0 0
    
     */
    View Code
  • 相关阅读:
    金额转换问题
    进制转换(十进制->二进制、八进制、十六进制)
    Linux下Tomcat的安装
    Linux下安装jdk配置java环境变量
    Linux下安装Mysql
    在Linux下安装Redis
    Redis常用操作
    阿里云服务器部署tomcat服务器无法访问
    mysql 创建数据库 编码
    docker 安装oracle
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11378192.html
Copyright © 2020-2023  润新知