hdu 5.3.3 3584 Cube

来源:互联网 发布:java调用void方法 编辑:程序博客网 时间:2024/05/03 03:33

先贴一些新的树状数组的东西。。当然都是各处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 51 1 1 1  1 1 10 1 1 11 1 1 1  2 2 20 1 1 10 2 2 2
 
Sample Output
101
 

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

粘贴党:

每次修改的时候,给定一个格子修改的范围(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……要不要这么懒啊喂!

不管怎样,树状数组的基础题会做了,撒花~


原创粉丝点击