• HDU3584cube三维树状数组


    原理很简单,就是三维树状数组模型。理解了三维树状数组,就可以直接秒杀。但是,三维的不好理解。只能由二维的去推广咯。

    二维的如下(采自某大牛,感谢,膜拜v):

    模式二:随时修改数组 a[] 中某个区间的值(O(1)),查询某个元素的值(O(logn))

    在这种模式下,a[i] 已经不再表示真实的值了,只不过是一个没有意义的、用来辅助的数组。这时我们真正需要的是另一个假想的数组 b[],b[i] 才表示真实的元素值。但 c[] 数组却始终是为 a[] 数组服务的,这一点大家要明确。此时 Getsum(i) 虽然也是求 a[i] 之前的元素和,但它现在表示的是实际我要的值,也就是 b[i]。
    比如现在我要对图1 中 a[] 数组中红色区域的值全部加1。当然你可以用模式一的 Modify(i) 对该区间内的每一个元素都修改一次,但如果这个区间很大,那么每次修改的复杂度就都是 O(nlogn),m 次修改就是 O(mnlogn),这在 m 和 n 很大的时候仍是不满足要求的。这时模式二便派上了用场。我只要将该区域的第一个元素 +1,最后一个元素的下一位置 -1,对每个位置 Getsum(i) 以后的值见图2:


    相信大家已经看得很清楚了,数组 b[] 正是我们想要的结果。模式二难理解主要在于 a[] 数组的意义。这时请不要再管 a[i] 表示什么,a[i] 已经没有意义了,我们需要的是 b[i]!但模式二同样存在一个缺陷,如果要对某个区间内的元素求和,就必须对该区间内的每个位置都作一次 Getsum(i),求出所有位置的真实元素值然后累加,这样复杂度又变成 O(nlogn) 了。所以要分清两种模式的优缺点,根据题目的条件选择合适的模式,灵活应变!

    顺便给出二维树状数组模式二的修改方法:

    #include<iostream>
    #define N 105
    #define lowbit(x) x&(-x)
    using namespace
    std;

    int
    tree[N][N][N];
    void
    add(int a,int b,int c,int n)
    {

        int
    i,j,k;
        for
    (i=a;i<N;i+=lowbit(i))
            for
    (j=b;j<N;j+=lowbit(j))
                for
    (k=c;k<N;k+=lowbit(k))
                {

                    tree[i][j][k]+=n;
                }
    }


    int
    subsum(int a,int b,int c)
    {

        int
    i,j,k,sum=0;
        for
    (i=a;i>0;i-=lowbit(i))
            for
    (j=b;j>0;j-=lowbit(j))
                for
    (k=c;k>0;k-=lowbit(k))
                {

                    sum+=tree[i][j][k];
                }

        return
    sum;
    }


    int
    main(void)
    {

        int
    i,j,k,m,n,sel,x1,y1,z1,x2,y2,z2;
        int
    sum;
        while
    (scanf("%d%d",&n,&m)==2)
        {

            for
    (i=0;i<N;i++)
                for
    (j=0;j<N;j++)
                    for
    (k=0;k<N;k++)
                        tree[i][j][k]=0;
            for
    (i=0;i<m;i++)
            {

                scanf("%d",&sel);
                if
    (sel==1)
                {

                    scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
                    //cout<<"fsdf";
                    add(x1,y1,z1,1);
                    add(x2+1,y1,z1,-1);
                    add(x1,y2+1,z1,-1);
                    add(x1,y1,z2+1,-1);
                    add(x2+1,y2+1,z1,1);
                    add(x1,y2+1,z2+1,1);
                    add(x2+1,y1,z2+1,1);
                    add(x2+1,y2+1,z2+1,-1);
                }

                else

                {

                    scanf("%d%d%d",&x1,&y1,&z1);
                    sum=subsum(x1,y1,z1);
                    if
    ((sum&1)==0)
                        printf("0\n");
                    else

                        printf("1\n");
                }
            }
        }

        return
    0;
    }

  • 相关阅读:
    生成doc
    Struts2 配置
    Struts(一)struts2.2概述与MVC模式深度剖析
    [DOM Event Learning] Section 4 事件分发和DOM事件流
    jquery 高亮显示案例
    jquery 下拉菜单
    3_1:操作样式
    2_2:筛选器
    2_1:选择元素
    本地存储小案例:记住用户名
  • 原文地址:https://www.cnblogs.com/cchun/p/2520086.html
Copyright © 2020-2023  润新知