zoukankan      html  css  js  c++  java
  • 白色长方形【扫描线】

    题目链接

      我们可以讲块坐标改成点坐标,然后再进行离散化,然后就是一个经典的扫面线问题了,如果b大于1的时候,横着扫完再竖着扫一遍就可以了。

      这时候扫描线的pushup该怎么写呢?我们用ls记录当前线段树上的节点的左连续白色的长度,rs记录当前线段树上的节点的右连续白色的长度,tree记录当前线段树上的节点对应的长b宽1的长方形的个数。

      于是,pushup就变成了如下情况:

       tree[rt] = tree[lsn] + tree[rsn];

    (1)如果rs[lsn] >= b && ls[rsn] >= b,此时tree[rt] += b - 1;因为两边的中间合并,并且两边都各自算过贡献了,(b-1)被多算了一遍,所以要加回去;

    (2)如果只有rs[lsn] >= b,此时再加上个ls[rsn]即可;

    (3)同理ls[rsn] >= b;

    (4)剩下的,如果rs[lsn] + ls[rsn] >= b,tree[rt] += rs[lsn] + ls[rsn] - b + 1。

      于是,剩下就是简单的扫描线问题了。

      当然, 一定不要写错lsn和rsn,不然debug还是蛮累的。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <bitset>
    #include <unordered_map>
    #include <unordered_set>
    #define lowbit(x) ( x&(-x) )
    #define pi 3.141592653589793
    #define e 2.718281828459045
    #define INF 0x3f3f3f3f
    #define HalF (l + r)>>1
    #define lsn rt<<1
    #define rsn rt<<1|1
    #define Lson lsn, l, mid
    #define Rson rsn, mid+1, r
    #define QL Lson, ql, qr
    #define QR Rson, ql, qr
    #define myself rt, l, r
    #define pii pair<int, int>
    #define MP(a, b) make_pair(a, b)
    using namespace std;
    typedef unsigned long long ull;
    typedef unsigned int uit;
    typedef long long ll;
    const int maxN = 2e5 + 7;
    int C, V, N, a, b, lsan[maxN], _UP;
    struct Matrice
    {
        int lx, ly, rx, ry;
        void In() { scanf("%d%d%d%d", &lx, &ly, &rx, &ry); rx ++; ry ++; }
    } t[maxN];
    struct Line
    {
        int l, r, y, op;
        Line(int a=0, int b=0, int c=0, int d=0):l(a), r(b), y(c), op(d) {}
        friend bool operator < (Line e1, Line e2)
        { return e1.y == e2.y ? e1.op > e2.op : e1.y < e2.y; }
    } edge[maxN];
    const int maxP = maxN << 2;
    int ls[maxP], rs[maxP], tree[maxP];
    ll ans = 0;
    void build(int rt, int l, int r)
    {
        ls[rt] = rs[rt] = lsan[r + 1] - lsan[l];
        if(ls[rt] >= b) tree[rt] = ls[rt] - b + 1;
        if(l == r) return;
        int mid = HalF;
        build(Lson);
        build(Rson);
    }
    void pushup(int rt, int l, int r)
    {
        int mid = HalF;
        ls[rt] = ls[lsn];
        rs[rt] = rs[rsn];
        if(ls[lsn] == lsan[mid + 1] - lsan[l]) ls[rt] += ls[rsn];
        if(rs[rsn] == lsan[r + 1] - lsan[mid + 1]) rs[rt] += rs[lsn];
        tree[rt] = tree[lsn] + tree[rsn];
        if(ls[rsn] + rs[lsn] >= b)
        {
            if(ls[rsn] >= b && rs[lsn] >= b) tree[rt] += b - 1;
            else if(ls[rsn] >= b) tree[rt] += rs[lsn];
            else if(rs[lsn] >= b) tree[rt] += ls[rsn];
            else tree[rt] += ls[rsn] + rs[lsn] - b + 1;
        }
    }
    void update(int rt, int l, int r, int ql, int qr, int val)
    {
        if(ql <= l && qr >= r)
        {
            if(val > 0)
            {
                ls[rt] = rs[rt] = lsan[r + 1] - lsan[l];
                if(ls[rt] >= b) tree[rt] = ls[rt] - b + 1;
            }
            else
            {
                ls[rt] = rs[rt] = 0;
                tree[rt] = 0;
            }
            return;
        }
        int mid = HalF;
        if(qr <= mid) update(QL, val);
        else if(ql > mid) update(QR, val);
        else { update(QL, val); update(QR, val); }
        pushup(myself);
    }
    void Solve()
    {
        _UP = 0;
        int n = 0;
        for(int i = 1; i <= N; i ++)
        {
            lsan[++ _UP] = t[i].ly;
            lsan[++ _UP] = t[i].ry;
            edge[++ n] = Line(t[i].ly, t[i].ry, t[i].lx, -1);
            edge[++ n] = Line(t[i].ly, t[i].ry, t[i].rx, +1);
        }
        lsan[++ _UP] = 1; lsan[++ _UP] = V;
        sort(lsan + 1, lsan + _UP + 1);
        _UP = (int)(unique(lsan + 1, lsan + _UP + 1) - lsan - 1);
        sort(edge + 1, edge + n + 1);
        build(1, 1, _UP - 1);
        if(n) ans += 1LL * (edge[1].y - 1) * tree[1];
        else ans += 1LL * (C - 1) * tree[1];
        for(int i = 1, ql, qr; i <= n; i ++)
        {
            ql = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].l) - lsan);
            qr = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].r) - lsan - 1);
            update(1, 1, _UP - 1, ql, qr, edge[i].op);
            if(i < n) ans += 1LL * (edge[i + 1].y - edge[i].y) * tree[1];
            else ans += 1LL * (C - edge[i].y) * tree[1];
        }
    }
    int main()
    {
        scanf("%d%d%d%d%d", &C, &V, &N, &a, &b); C ++; V ++;
        for(int i = 1; i <= N; i ++) t[i].In();
        _UP = 0;
        int n = 0;
        for(int i = 1; i <= N; i ++)
        {
            lsan[++ _UP] = t[i].lx;
            lsan[++ _UP] = t[i].rx;
            edge[++ n] = Line(t[i].lx, t[i].rx, t[i].ly, -1);
            edge[++ n] = Line(t[i].lx, t[i].rx, t[i].ry, +1);
        }
        lsan[++ _UP] = 1; lsan[++ _UP] = C;
        sort(lsan + 1, lsan + _UP + 1);
        _UP = (int)(unique(lsan + 1, lsan + _UP + 1) - lsan - 1);
        sort(edge + 1, edge + n + 1);
        build(1, 1, _UP - 1);
        if(n) ans += 1LL * (edge[1].y - 1) * tree[1];
        else ans += 1LL * (V - 1) * tree[1];
        for(int i = 1, ql, qr; i <= n; i ++)
        {
            ql = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].l) - lsan);
            qr = (int)(lower_bound(lsan + 1, lsan + _UP + 1, edge[i].r) - lsan - 1);
            update(1, 1, _UP - 1, ql, qr, edge[i].op);
            if(i < n) ans += 1LL * (edge[i + 1].y - edge[i].y) * tree[1];
            else ans += 1LL * (V - edge[i].y) * tree[1];
        }
        if(b > 1)
        {
            Solve();
        }
        printf("%lld
    ", ans);
        return 0;
    }
    /*
    4 4 2 1 2
    1 1 2 2
    3 3 4 4
    ans:8
    */
  • 相关阅读:
    学习进度四
    每日进度二
    每日进度一
    学习进度三
    学习进度二
    安全性战术
    Linux 常用命令
    python测试框架之pytest
    Python 列表生成式和字典生成式
    使用Python在Windows 10上显示通知信息
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/14504467.html
Copyright © 2011-2022 走看看