• Get The Treasury【HDU-3642】【扫描线】


    题目链接

      题目给出的是N个体积块,问的是有多少体积重叠了3次及以上?

      那么就是怎么处理体积这样子的问题了,看到Z的种类不多的时候,就想着从Z离散化的角度去考虑这个问题了,然后就是怎样子去处理面积了,这时候想到每一个Z所代表的这个面对应上的体积,然后把每个面都处理出来看,体积就是在处理X的和,以及求Y、Z的差(差分)来的乘积,所以在处理Z上的时候也有些细节的东西,就是我们要考虑到目前所访问到的这个面积段是否是可以取的,也就是要去判断它的上下Z坐标和目前的区间的上下Z坐标的关系式了。

      另外,在处理pushup()的时候,也是需要注意细节,我在这里处理的是"≥times"也就是覆盖次数大于等于1的线段的长、大于等于2的线段的长……

    剩下的吧,基本就是写代码上的,细心点,没什么其他的了。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #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
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int maxN = 1e3 + 7;
    int N, X[maxN<<1], tot, Z[maxN<<1], cnt, lsan_Z, _UP;
    struct IOput
    {
        int lx, ly, lz, rx, ry, rz;
    }a[maxN];
    struct node
    {
        int lx, rx, y, val;
        node(int a=0, int b=0, int c=0, int d=0):lx(a), rx(b), y(c), val(d) {}
    }line[maxN<<1];
    bool cmp(node e1, node e2) { return e1.y < e2.y; }
    struct Tree
    {
        int siz, sum, len1, len2;   //求的是"≥times"的数的个数和
        void clear() { siz = sum = len1 = len2 = 0; }
    }t[maxN<<3];
    inline void buildTree(int rt, int l, int r)
    {
        t[rt].clear();
        if(l == r) return;
        int mid = HalF;
        buildTree(Lson);
        buildTree(Rson);
    }
    inline void pushup(int rt, int l, int r)
    {
        if(t[rt].siz >= 3)
        {
            t[rt].sum = t[rt].len2 = t[rt].len1 = X[r + 1] - X[l];
        }
        else if(t[rt].siz == 2)
        {
            t[rt].sum = t[lsn].len1 + t[rsn].len1;
            t[rt].len2 = t[rt].len1 = X[r + 1] - X[l];
        }
        else if(t[rt].siz == 1)
        {
            t[rt].sum = t[lsn].len2 + t[rsn].len2;
            if(l == r) t[rt].len2 = 0;  //相等的时候记得清空对应值
            else t[rt].len2 = t[lsn].len1 + t[rsn].len1;
            t[rt].len1 = X[r + 1] - X[l];
        }
        else if(l == r) t[rt].clear();
        else
        {
            t[rt].sum = t[lsn].sum + t[rsn].sum;
            t[rt].len2 = t[lsn].len2 + t[rsn].len2;
            t[rt].len1 = t[lsn].len1 + t[rsn].len1;
        }
    }
    inline void update(int rt, int l, int r, int ql, int qr, int val)
    {
        if(ql <= l && qr >= r)
        {
            t[rt].siz += val;
            pushup(myself);
            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);
    }
    inline void init()
    {
        cnt = 0;
    }
    int main()
    {
        int T;  scanf("%d", &T);
        for(int Cas=1; Cas<=T; Cas++)
        {
            scanf("%d", &N);
            init();
            for(int i=1; i<=N; i++)
            {
                scanf("%d%d%d%d%d%d", &a[i].lx, &a[i].ly, &a[i].lz, &a[i].rx, &a[i].ry, &a[i].rz);
                Z[++cnt] = a[i].lz;
                Z[++cnt] = a[i].rz;
            }
            sort(Z + 1, Z + cnt + 1);
            lsan_Z = (int)(unique(Z + 1, Z + cnt + 1) - Z - 1);
            ll ans = 0;
            for(int u=1; u<lsan_Z; u++)
            {
                tot = 0;
                for(int i=1; i<=N; i++)
                {
                    if(a[i].lz <= Z[u] && a[i].rz > Z[u])   //不能计算前面已经算过的部分,就是存在头即尾的情况
                    {
                        line[++tot] = node(a[i].lx, a[i].rx, a[i].ly, 1);
                        X[tot] = a[i].lx;
                        line[++tot] = node(a[i].lx, a[i].rx, a[i].ry, -1);
                        X[tot] = a[i].rx;
                    }
                }
                sort(line + 1, line + tot + 1, cmp);
                sort(X + 1, X + tot + 1);
                _UP = (int)(unique(X + 1, X + tot + 1) - X - 1);
                memset(t, 0, sizeof(t));
                for(int i=1, l, r; i<tot; i++)
                {
                    l = (int)(lower_bound(X + 1, X + _UP + 1, line[i].lx) - X);
                    r = (int)(lower_bound(X + 1, X + _UP + 1, line[i].rx) - X - 1);
                    update(1, 1, _UP, l, r, line[i].val);
                    ans += (ll)(Z[u + 1] - Z[u]) * (ll)(line[i + 1].y - line[i].y) * (t[1].sum);
                }
            }
            printf("Case %d: %lld
    ", Cas, ans);
        }
        return 0;
    }
    /*
    1
    6
    1 0 0 2 2 2
    0 1 0 2 2 2
    0 0 1 2 2 2
    1 0 0 2 2 2
    0 1 0 2 2 2
    0 0 1 2 2 2
    ans = 4
    */
    View Code
  • 相关阅读:
    【tyvj1952】easy
    【noip2005】篝火晚会
    BZOJ4818: [Sdoi2017]序列计数
    BZOJ2436: [Noi2011]Noi嘉年华
    BZOJ4826: [Hnoi2017]影魔
    BZOJ4540: [Hnoi2016]序列
    BZOJ4827: [Hnoi2017]礼物
    BZOJ3527: [Zjoi2014]力
    BZOJ4407: 于神之怒加强版
    BZOJ1854: [Scoi2010]游戏
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/10934718.html
Copyright © 2020-2023  润新知