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的个数
模版:
上新题:
三维的树状数组。想法很奇妙,将区间修改点查询硬是绕回了点修改区间查询。
粘贴党:
每次修改的时候,给定一个格子修改的范围(x,y)。把这个范围变成两个点,一个为更改的初始节点x,另一个为终止结点y+1(不是y),然后这两个节点加1,向根节点上溯,节点+1。
x y+1
insert x,y+1
每次询问x的时候只需计算sum=sigma(a[i],0<i<=x),即第x个数被修改了sum次,状态为sum%2。
三维即需要改8个点。
直接拿模版改得,感觉不错。不过还是有些小问题。
由于三重循环懒得打了经常会复制粘贴,修改时要注意细节。不要漏改了一些地方害的调代码半天。
三重循环时x可以直接减,但y和z都要循环几次,需要保留变量y,z的值。显然我是事后改得,用yy,zz保留值。其实比较正常的思路是用yy,zz做循环变量吧……不过现在这样可以少敲几个y和z……要不要这么懒啊喂!
不管怎样,树状数组的基础题会做了,撒花~
适用范围:
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 Input2 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 Output1 0 1 |
粘贴党:
每次修改的时候,给定一个格子修改的范围(x,y)。把这个范围变成两个点,一个为更改的初始节点x,另一个为终止结点y+1(不是y),然后这两个节点加1,向根节点上溯,节点+1。
x y+1
0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
每次询问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……要不要这么懒啊喂!
不管怎样,树状数组的基础题会做了,撒花~
相关文章推荐
- HDU 3584 Cube (三维树状数组)
- HDU - 3584 Cube(三维树状数组)
- HDU 3584 Cube(三维树状数组)
- HDU 3584 Cube(三位树状数组)
- hdu 3584 Cube
- hdu 3584 Cube(三维树状数组)
- hdu 1541 Stars poj 1195 Mobile phones(二维) poj 2155 Matrix(二维) hdu 3584 Cube(三维) 树状数组
- HDU 3584 Cube(三维BIT+容斥)
- HDU 3584 Cube(三维树状数组)
- HDU 3584 Cube
- hdu 3584 Cube (三维树状数组)
- hdu 3584 Cube
- HDU 3584 Cube(三维树状数组)
- HDU 3584 Cube(三维树状数组)
- poj 2155 Matrix(二维树状数组) hdu 3584 Cube(三维)
- HDU 3584 Cube
- HDU - 3584 - Cube (树状数组+容斥)
- HDU - 3584 Cube (三维树状数组 + 区间改动 + 单点求值)
- hdu 3584 Cube(树状数组)
- HDU 3584 Cube(三位树状数组)