您的位置:首页 > 其它

hdu 5.3.3 3584 Cube

2012-02-02 12:56 211 查看
先贴一些新的树状数组的东西。。当然都是各处ctrl+c来的……

适用范围:

1 下标要从1开始

2 常用于修改一个点a[i],查询区间和的情况c[i]

3 适用范围是必须符合减法原则,也就是说不能用于求一个区间范围内的最值
k&(-k):将k化为二进制时末尾0的个数

模版:

int lowbit(int x)//计算lowbit
{
    return x&(-x);
}
void add(int i,int val)//将第i个元素更改为val
{
    while(i<=n)
    {
        c[i]+=val;
        i+=lowbit(i);
    }
}
int sum(int i)//求前i项和
{
    int s=0;
    while(i>0)
    {
        s+=c[i];
        i-=lowbit(i);
    }
    return s;
}
差不多就这样,以后看到继续补充吧。

上新题:

Cube

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 22 Accepted Submission(s): 19
Problem Description

Given an N*N*N cube A, whose elements are either 0 or 1. A[i, j, k] means the number in the i-th row , j-th column and k-th layer. Initially we have A[i, j, k] = 0 (1 <= i, j, k <= N).

We define two operations, 1: “Not” operation that we change the A[i, j, k]=!A[i, j, k]. that means we change A[i, j, k] from 0->1,or 1->0. (x1<=i<=x2,y1<=j<=y2,z1<=k<=z2).

0: “Query” operation we want to get the value of A[i, j, k].


Input

Multi-cases.

First line contains N and M, M lines follow indicating the operation below.

Each operation contains an X, the type of operation. 1: “Not” operation and 0: “Query” operation.

If X is 1, following x1, y1, z1, x2, y2, z2.

If X is 0, following x, y, z.


Output

For each query output A[x, y, z] in one line. (1<=n<=100 sum of m <=10000)


Sample Input

2 5
1 1 1 1  1 1 1
0 1 1 1
1 1 1 1  2 2 2
0 1 1 1
0 2 2 2



Sample Output

1
0
1



三维的树状数组。想法很奇妙,将区间修改点查询硬是绕回了点修改区间查询。

粘贴党:

每次修改的时候,给定一个格子修改的范围(x,y)。把这个范围变成两个点,一个为更改的初始节点x,另一个为终止结点y+1(不是y),然后这两个节点加1,向根节点上溯,节点+1。

x y+1
0010010000
insert x,y+1

每次询问x的时候只需计算sum=sigma(a[i],0<i<=x),即第x个数被修改了sum次,状态为sum%2。

三维即需要改8个点。

#include <iostream>
using namespace std;

int n;
int c[102][102][102];

int lowbit(int x)//计算lowbit
{
    return x&(-x);
}
void add(int x,int y,int z)//将第i个元素更改为val
{
     int yy=y,zz=z;
     for(;x<=n;x+=lowbit(x))
         for(y=yy;y<=n;y+=lowbit(y))
             for(z=zz;z<=n;z+=lowbit(z))
                 c[x][y][z]^=1;//c=!c
}
int sum(int x,int y,int z)//求前i项和
{
    int s=0;
    int yy=y,zz=z;
    for(;x>0;x-=lowbit(x))
         for(y=yy;y>0;y-=lowbit(y))
             for(z=zz;z>0;z-=lowbit(z))
                 //s=(s+c[x][y][z])&1;
                 s^=c[x][y][z];
    cout<<s<<endl;
}

int main()
{
    int m;
    while(cin>>n>>m)
    {
        memset(c,0,sizeof(c));
        while(m--)
        {
            int s;
            int x1,y1,z1,x2,y2,z2;
            scanf("%d",&s);
            if(s)
            {
                 scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
                 add(x1,y1,z1);//eight point
                 add(x1,y2+1,z1);
                 add(x1,y2+1,z2+1);
                 add(x1,y1,z2+1);
                 add(x2+1,y1,z1);
                 add(x2+1,y2+1,z1);
                 add(x2+1,y2+1,z2+1);
                 add(x2+1,y1,z2+1);
            }
            else
            {
                scanf("%d%d%d",&x1,&y1,&z1);
                sum(x1,y1,z1);
            }
        }
    }
    return 0;
}


直接拿模版改得,感觉不错。不过还是有些小问题。

由于三重循环懒得打了经常会复制粘贴,修改时要注意细节。不要漏改了一些地方害的调代码半天。

三重循环时x可以直接减,但y和z都要循环几次,需要保留变量y,z的值。显然我是事后改得,用yy,zz保留值。其实比较正常的思路是用yy,zz做循环变量吧……不过现在这样可以少敲几个y和z……要不要这么懒啊喂!

不管怎样,树状数组的基础题会做了,撒花~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: