zoukankan      html  css  js  c++  java
  • 2019牛客第八场多校 D_Distance 三维BIT或定期重建套路

    @

    题意:

    在三维空间((n imes m imes hle 100000))内,有(q(qle 100000))次操作。操作(1):添加一个点进入空间;操作(2):查询最近点对。


    分析:

    比赛时听G黄说完题意感觉看似好像裸题,一道在二维平面上操作完全的题:BZOJ2716
    那么KD-Tree还是四维偏序问题呢?(原来都不是。。出题人放出豪言:KD-Tree想过?不可能的
    解法1:三维BIT - 862ms

    • 把曼哈顿距离的绝对值去掉后,共有8种情况。
    • 用8个BIT把每个点拆掉绝对值后的8种贡献记录一下即可。
    • 比如这种情况:这个点在其他点的左后下方时:(len=|x1-x2|+|y1-y2|+|z1-z2|=(x1+y1+z1)-(x2+y2+z2))。就(update(x2,y2,z2)),值为(-(x2+y2+z2))。以此类推。
    • 我们知道对于两个确定的点,他们相对位置也确定了,显然(p2)在用(p1)的正确相对位置的(query())求出来的距离一定是最小的。这种做法正确性十分显然。然后BIT常数非常小,很容易过去的。

    解法2:定期重构+BFS - 86ms (ps:好像是最快的
    定期重构这应该是一个很常见的套路的吧?有些分块好像经常有这种操作?
    在这里插入图片描述

    • 对三维空间维护一个值(dis[i]),表示离当前点(i)位置的最近点距离。
    • 当新加入的点的数量小于阈值MX时,暴力比对这些新加入的点。
    • 当达到了阈值MX时,就用这些新加入的点松弛我们的(dis[])即可。
    • 代码挺好懂的。。。
      Code1
    const int MXN = 3e3 + 7;  
    const int MXE = 2e6 + 7;  
    typedef vector<int> VI;  
    typedef vector<VI > VVI;  
    typedef vector<VVI > VVVI;  
    //mat c(a.size(), vec(b[0].size(), 0));
    //VVVI bit(n+1,VVI(m+1, VI(h+1, INF)));
    int n, m, h, q;  
    struct BIT {  
        int n, m, h;  
        vector<vector<vector<int> > > bit;  
        void init(int _n, int _m, int _h) {  
            n = _n, m = _m, h = _h;  
            bit = VVVI(n+1,VVI(m+1, VI(h+1, INF)));  
        }  
        void update(int _x, int _y, int _z, int v) {  
            for(int x = _x; x <= n; x += lowbit(x)) {  
                for(int y = _y; y <= m; y += lowbit(y)) {  
                    for(int z = _z; z <= h; z += lowbit(z)) {  
                        bit[x][y][z] = sml(bit[x][y][z], v);  
                    }  
                }  
            }  
        }  
        int query(int _x, int _y, int _z) {  
            int res = INF;  
            for(int x = _x; x > 0; x -= lowbit(x)) {  
                for(int y = _y; y > 0; y -= lowbit(y)) {  
                    for(int z = _z; z > 0; z -= lowbit(z)) {  
                        res = sml(bit[x][y][z], res);  
                    }  
                }  
            }  
            return res;  
        }  
    }bit[8];  
    int main() {  
    #ifndef ONLINE_JUDGE  
      freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);  
    //    freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);  
    #endif  
      n = read(), m = read(), h = read(), q = read();  
        int opt, x, y, z, ans;  
        for(int i = 0; i < 8; ++i) bit[i].init(n, m, h);  
        while(q --) {  
            opt = read(), x = read(), y = read(), z = read();  
            if(opt == 1) {  
                for(int i = 0; i < 8; ++i) {  
                    int v = (i&1?x:-x) + ((i>>1)&1?y:-y) + ((i>>2)&1?z:-z);  
    //                debug(i, i&1?x:n+1-x, (i>>1)&1?y:m+1-y, (i>>2)&1?z:h+1-z, v)  
    //                debug(i&1?n+1-x:x, (i>>1)&1?m+1-y:y, (i>>2)&1?h+1-z:z)  
      bit[i].update(i&1?n+1-x:x, (i>>1)&1?m+1-y:y, (i>>2)&1?h+1-z:z, v);  
                }  
            }else {  
                ans = INF;  
                for(int i = 0; i < 8; ++i) {  
                    int v = (i&1?-x:x) + ((i>>1)&1?-y:y) + ((i>>2)&1?-z:z);  
    //                debug(x, y, z)  
    //                debug(opt, i&1?n+1-x:x, (i>>1)&1?m+1-y:y, (i>>2)&1?h+1-z:z)  
      ans = sml(ans, v + bit[i].query(i&1?n+1-x:x, (i>>1)&1?m+1-y:y, (i>>2)&1?h+1-z:z));  
                }  
                printf("%d
    ", ans);  
            }  
        }  
        return 0;  
    }
    

    Code2

    const int MXN = 1e6 + 7;  
    const int MXE = 2e6 + 7;  
    typedef vector<int> VI;  
    typedef vector<VI > VVI;  
    typedef vector<VVI > VVVI;  
    //mat c(a.size(), vec(b[0].size(), 0));  
    int n, m, h, q;  
    const int MX = 1000;  
    VI X, Y, Z;  
    int dis[MXN];  
    namespace lh {  
        int hash(int x, int y, int z) {  
            return x * m * h + y * h + z;  
        }  
    }  
    struct lp {  
        int x, y, z;  
    };  
    int dir[6][3] = {1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1};  
    void rebuild() {  
        queue<lp> Q;  
        for(int i = 0; i < SZ(X); ++i) {  
            dis[lh::hash(X[i], Y[i], Z[i])] = 0;  
            Q.push({X[i], Y[i], Z[i]});  
        }  
        while(!Q.empty()) {  
            lp A = Q.front(); Q.pop();  
            for(int i = 0; i < 6; ++i) {  
                int px = A.x + dir[i][0], py = A.y + dir[i][1], pz = A.z + dir[i][2];  
                if(px < 0 || py < 0 || pz < 0 || px >= n || py >= m || pz >= h || dis[lh::hash(px, py, pz)] <= dis[lh::hash(A.x, A.y, A.z)] + 1) continue;  
                dis[lh::hash(px, py, pz)] = dis[lh::hash(A.x, A.y, A.z)] + 1;  
                Q.push(lp{px, py, pz});  
            }  
        }  
        X.clear(), Y.clear(), Z.clear();  
    }  
    int main() {  
    #ifndef ONLINE_JUDGE  
      freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);  
    //    freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);  
    #endif  
      n = read(), m = read(), h = read(), q = read();  
        int opt, x, y, z, ans;  
        clr(dis, 0x3f);  
        while(q --) {  
            opt = read(), x = read(), y = read(), z = read();  
            -- x, -- y, -- z;  
            if(opt == 1) {  
                X.eb(x), Y.eb(y), Z.eb(z);  
            }else {  
                ans = dis[lh::hash(x, y, z)];  
                for(int i = 0; i < SZ(X); ++i) ans = sml(ans, abs(x - X[i]) + abs(y - Y[i]) + abs(z - Z[i]));  
                printf("%d
    ", ans);  
            }  
            if(1 || SZ(X) == MX) rebuild();  
        }  
        return 0;  
    }
    
  • 相关阅读:
    iconv 文件编码相互转换
    MySQL 字符编码
    MySQL there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause同时创建多个更新当前时间戳字段 解决方法
    PHP 输出日志到文件 DEMO
    Nginx http -> https 跳转后 POST 丢失
    SSH SCP 远程密钥登录配置和服务器间的文件传输
    Mac 安装 7zip
    git pull There is no tracking information for the current branch.
    MacOS 安装配置 Laravel
    Mac OS 安装 MySQL5.7
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/11333344.html
Copyright © 2011-2022 走看看