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;
    }
    
  • 相关阅读:
    【404】int main(int argc,char * argv[]) windows 下的使用
    【403】COMP9024 Exercise
    【402】Twitter Data Collection
    【401】Python 求合数的所有质数因子
    【400】numpy.pad 为数组加垫(迷宫类题目)
    iOS开发之指纹解锁
    iOS-响应链(Responder Chain)
    iOS上手指点击波纹效果的实现
    使用methodSignatureForSelector与forwardInvocation实现消息转发 (转)
    Objective-C中的@dynamic(转)
  • 原文地址:https://www.cnblogs.com/Dillonh/p/11332789.html
Copyright © 2011-2022 走看看