zoukankan      html  css  js  c++  java
  • Distance(2019年牛客多校第八场D题+CDQ+树状数组)

    题目链接

    传送门

    思路

    这个题在(BZOJ)上有个二维平面的版本((BZOJ2716)天使玩偶),不过是权限题因此就不附带链接了,我也只是在算法进阶指南上看到过,那个题的写法是(CDQ),然后比赛开始半个小时我就开始写(CDQ)(T)了之后冷静分析发现复杂度我少算了个(log)(CDQ)写这题的复杂度是(nlog^3(n)),然后就没思路了。

    赛后看(qls)说用三维(bit)可以过后试了一下(T)了,然后发现(qls)的代码当时跑了(937ms)应该是卡过去的,感觉是(vector)常数大,但是想不出除(vector)的其他动态开全局数组大小的方法,最后疯狂交在(T)了一页后成功卡过去了,下面贴一下三维(bit)的代码和(CDQ)写法(对拍了很久貌似没问题,就当过了吧~)的代码。

    这两份代码的主体思路就是拆绝对值符号,然后查询时(拿(x_1leq x2,y_1leq y2,z_1leq z_2)举例,下标为(2)的是查询的点)(|x_2-x_1|+|y_2-y_1|+|z_2-z_1|=(x_2+y_2+z_2)-(x_1+y_1+z_1)),然后就是要查询(x_1+y_1+z_1)的最大值用树状数组维护即可,其他情况分别移动坐标即可。

    update:发现题解里面贴的那份代码的三维(bit)写法贼牛逼,贴的代码就改成看了那个队的代码之后写的了。

    代码

    //三维bit
    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cassert>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, LL> pLL;
    typedef pair<LL, int> pLi;
    typedef pair<int, LL> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    
    #define lson rt<<1
    #define rson rt<<1|1
    #define lowbit(x) x&(-x)
    #define name2str(name) (#name)
    #define bug printf("*********
    ")
    #define debug(x) cout<<#x"=["<<x<<"]" <<endl
    #define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    
    const double eps = 1e-8;
    const int mod = 1000000007;
    const int maxn = 800000 + 7;
    const double pi = acos(-1);
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3fLL;
    
    int n, m, h, q, op, x, y, z;
    
    struct BIT {
        int a[maxn];
    
        int gethash(int x, int y, int z) {
            return x * h * m + y * h + z;
        }
    
        void init() {
            for(int i = 0; i <= n; ++i) {
                for(int j = 0; j <= m; ++j) {
                    for(int k = 0; k <= h; ++k) {
                        a[gethash(i, j, k)] = 0;
                    }
                }
            }
        }
    
        void update(int x, int y, int z) {
            for(int i = x; i <= n; i += lowbit(i)) {
                for(int j = y; j <= m; j += lowbit(j)) {
                    for(int k = z; k <= h; k += lowbit(k)) {
                        int num = gethash(i, j, k);
                        a[num] = max(a[num], x + y + z);
                    }
                }
            }
        }
    
        int query(int x, int y, int z) {
            int ans = 0;
            for(int i = x; i > 0; i -= lowbit(i)) {
                for(int j = y; j > 0; j -= lowbit(j)) {
                    for(int k = z; k > 0; k -= lowbit(k)) {
                        ans = max(ans, a[gethash(i, j, k)]);
                    }
                }
            }
            if(ans == 0) return inf;
            return x + y + z - ans;
        }
    }bit[8];
    
    int main() {
        scanf("%d%d%d%d", &n, &m, &h, &q);
        n += 1, m += 1, h += 1;
        for(int i = 0; i < 8; ++i) bit[i].init();
        for(int  i = 1; i <= q; ++i) {
            scanf("%d%d%d%d", &op, &x, &y, &z);
            if(op == 1) {
                bit[1].update(x, y, z);
                bit[2].update(x, y, h - z);
                bit[3].update(x, m - y, z);
                bit[4].update(n - x, y, z);
                bit[5].update(n - x, m - y, z);
                bit[6].update(n - x, y, h - z);
                bit[7].update(x, m - y, h - z);
                bit[0].update(n - x, m - y, h - z);
            } else {
                int ans = inf;
                ans = min(ans, bit[1].query(x, y, z));
                ans = min(ans, bit[2].query(x, y, h - z));
                ans = min(ans, bit[3].query(x, m - y, z));
                ans = min(ans, bit[4].query(n - x, y, z));
                ans = min(ans, bit[5].query(n - x, m - y, z));
                ans = min(ans, bit[6].query(n - x, y, h - z));
                ans = min(ans, bit[7].query(x, m - y, h - z));
                ans = min(ans, bit[0].query(n - x, m - y, h - z));
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
    
    //CDQ
    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cassert>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, LL> pLL;
    typedef pair<LL, int> pLi;
    typedef pair<int, LL> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    
    #define lson rt<<1
    #define rson rt<<1|1
    #define lowbit(x) x&(-x)
    #define name2str(name) (#name)
    #define bug printf("*********
    ")
    #define debug(x) cout<<#x"=["<<x<<"]" <<endl
    #define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    
    const double eps = 1e-8;
    const int mod = 1000000007;
    const int maxn = 100001;
    const double pi = acos(-1);
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3fLL;
    
    int n, m, h, q, op, x, y, z;
    int tree[maxn], ans[maxn];
    
    struct node {
        int id, x, y, z, op, val, flag;
        bool operator < (const node& a) const {
            return id < a.id;
        }
    }a[maxn], tmp[maxn], pp[maxn];
    
    void add(int x, int val) {
        while(x <= h) {
            tree[x] = max(tree[x], val);
            x += lowbit(x);
        }
    }
    
    int query(int x) {
        int ans = 0;
        while(x) {
            ans = max(ans, tree[x]);
            x -= lowbit(x);
        }
        if(ans == 0) ans = -inf;
        return ans;
    }
    
    void del(int x) {
        while(x <= h + 1) {
            tree[x] = 0;
            x += lowbit(x);
        }
    }
    
    void cdq2(int l, int r) {
        if(l == r) return;
        int mid = (l + r) >> 1;
        cdq2(l, mid), cdq2(mid + 1, r);
        int ls = l, rs = mid + 1, cnt = l;
        for(; rs <= r; ++rs) {
            for(; ls <= mid && tmp[ls].y <= tmp[rs].y; ++ls) {
                if(tmp[ls].op == 1 && tmp[ls].flag) {
                    add(tmp[ls].z, tmp[ls].val);
                }
            }
            if(!tmp[rs].flag && tmp[rs].op == 2) ans[tmp[rs].id] = min(ans[tmp[rs].id], tmp[rs].val - query(tmp[rs].z));
        }
        --ls;
        while(ls >= l) {
            if(tmp[ls].op == 1 && tmp[ls].flag) {
                del(tmp[ls].z);
            }
            --ls;
        }
        ls = l, rs = mid + 1;
        while(ls <= mid && rs <= r) {
            if(tmp[ls].y < tmp[rs].y) {
                pp[cnt++] = tmp[ls++];
            } else if(tmp[ls].y > tmp[rs].y) {
                pp[cnt++] = tmp[rs++];
            } else if(tmp[ls].z <= tmp[rs].z) {
                pp[cnt++] = tmp[ls++];
            } else {
                pp[cnt++] = tmp[rs++];
            }
        }
        while(ls <= mid) pp[cnt++] = tmp[ls++];
        while(rs <= r) pp[cnt++] = tmp[rs++];
        for(int i = l; i <= r; ++i) tmp[i] = pp[i];
    }
    
    void cdq1(int l, int r) {
        if(l == r) return;
        int mid = (l + r) >> 1;
        cdq1(l, mid), cdq1(mid + 1, r);
        int ls = l, rs = mid + 1, cnt = l;
        while(ls <= mid && rs <= r) {
            if(a[ls].x < a[rs].x) {
                tmp[cnt] = a[ls++];
                tmp[cnt++].flag = 1;
            } else if(a[ls].x > a[rs].x) {
                tmp[cnt] = a[rs++];
                tmp[cnt++].flag = 0;
            } else if(a[ls].y < a[rs].y) {
                tmp[cnt] = a[ls++];
                tmp[cnt++].flag = 1;
            } else if(a[ls].y > a[rs].y) {
                tmp[cnt] = a[rs++];
                tmp[cnt++].flag = 0;
            } else if(a[ls].z <= a[rs].z) {
                tmp[cnt] = a[ls++];
                tmp[cnt++].flag = 1;
            } else {
                tmp[cnt] = a[rs++];
                tmp[cnt++].flag = 0;
            }
        }
        while(ls <= mid) {
            tmp[cnt] = a[ls++];
            tmp[cnt++].flag = 1;
        }
        while(rs <= r) {
            tmp[cnt] = a[rs++];
            tmp[cnt++].flag = 0;
        }
        for(int i = l; i <= r; ++i) a[i] = tmp[i];
        cdq2(l, r);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        FIN;
    #endif
        scanf("%d%d%d%d", &n, &m, &h, &q);
        n += 1, m += 1, h += 1;
        for(int i = 1; i <= q; ++i) {
            scanf("%d%d%d%d", &op, &x, &y, &z);
            a[i] = {i, x, y, z, op, 0, 0};
        }
        //x,y,z
        for(int i = 1; i <= q; ++i) {
            ans[i] = inf;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        cdq1(1, q);
    
        //x,y,-z
        for(int i = 1; i <= q; ++i) {
            a[i].z = h - a[i].z;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        //x,-y,z
        for(int i = 1; i <= q; ++i) {
            a[i].z = h - a[i].z;
            a[i].y = m - a[i].y;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        //-x,y,z
        for(int i = 1; i <= q; ++i) {
            a[i].y = m - a[i].y;
            a[i].x = n - a[i].x;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        //-x,-y,z
        for(int i = 1; i <= q; ++i) {
            a[i].y = m - a[i].y;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        //-x,y,-z
        for(int i = 1; i <= q; ++i) {
            a[i].y = m - a[i].y;
            a[i].z = h - a[i].z;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        //x,-y,-z
        for(int i = 1; i <= q; ++i) {
            a[i].x = n - a[i].x;
            a[i].y = m - a[i].y;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        //-x,-y,-z
        for(int i = 1; i <= q; ++i) {
            a[i].x = n - a[i].x;
            a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
        }
        sort(a + 1, a + q + 1);
        cdq1(1, q);
    
        sort(a + 1, a + q + 1);
        for(int i = 1; i <= q; ++i) {
            if(a[i].op == 2) {
                printf("%d
    ", ans[i]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    友盟上报 IOS
    UTF8编码
    Hill加密算法
    Base64编码
    Logistic Regression 算法向量化实现及心得
    152. Maximum Product Subarray(中等, 神奇的 swap)
    216. Combination Sum III(medium, backtrack, 本类问题做的最快的一次)
    77. Combinations(medium, backtrack, 重要, 弄了1小时)
    47. Permutations II(medium, backtrack, 重要, 条件较难思考)
    3.5 find() 判断是否存在某元素
  • 原文地址:https://www.cnblogs.com/Dillonh/p/11332789.html
Copyright © 2011-2022 走看看