HDU 3584 Cube 【三维树状数组】
2010-09-04 23:50
363 查看
【题目地址】
http://acm.hdu.edu.cn/showproblem.php?pid=3584
【题目大意】
N*N*N的立方体,元素为0或1(初始为0)。1操作将(x1,y1,z1)到(x2,y2,z2)之间的元素取反;0操作是询问(x,y,z)为0或1。
【解题思路】
很容易想到三维线段树,但操作过于复杂。果断用树状数组,由一维开始:
每次修改的时候,给定一个格子修改的范围(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。
对于二维的情况,加上四个格子即可(x1,y1), (x1,y2+1), (x2+1,y1), (x2+1,y2+1),每次修改的时候这四个格子加1。
insert (x1,y1) (x1,y2+1) (x2+1,y1) (x2+1,y2+1)
查询(x,y)时输出sum=sigma(a[i][j],0<i<=x&&0<j<=y)即可。
三维的时候加8个点,n维加2^n个点。
PS:不懂树状数组的建议先学习 武钢三中 吴豪《树状数组》
引用:国家集训队2009论文集 武森《浅谈信息学竞赛中的“0”和“1”》
【代码】
http://acm.hdu.edu.cn/showproblem.php?pid=3584
【题目大意】
N*N*N的立方体,元素为0或1(初始为0)。1操作将(x1,y1,z1)到(x2,y2,z2)之间的元素取反;0操作是询问(x,y,z)为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。
对于二维的情况,加上四个格子即可(x1,y1), (x1,y2+1), (x2+1,y1), (x2+1,y2+1),每次修改的时候这四个格子加1。
(x1,y1) | 0 | 0 | (x2+1,y1) | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
(x1,y2+1) | 0 | 0 | (x2+1,y2+1) | 0 |
0 | 0 | 0 | 0 | 0 |
查询(x,y)时输出sum=sigma(a[i][j],0<i<=x&&0<j<=y)即可。
三维的时候加8个点,n维加2^n个点。
PS:不懂树状数组的建议先学习 武钢三中 吴豪《树状数组》
引用:国家集训队2009论文集 武森《浅谈信息学竞赛中的“0”和“1”》
【代码】
1: #include <cstdio>
2: #include <cstring>
3: #define maxn 105
4:
5: int c[maxn][maxn][maxn],len,wid,hgt;
6: int getsum(int i,int j,int r){
7: int tmpj,tmpr,sum=0;
8: while(i>0){
9: tmpj=j;
10: while(tmpj>0){
11: tmpr=r;
12: while(tmpr>0){
13: sum+=c[i][tmpj][tmpr];
14: tmpr-=(-tmpr)&tmpr;
15: }
16: tmpj-=(-tmpj)&tmpj;
17: }
18: i-=(-i)&i;
19: }
20: return sum;
21: }
22:
23: void insert(int i,int j,int r){
24: int tmpj,tmpr;
25: while(i<=len){
26: tmpj=j;
27: while(tmpj<=wid){
28: tmpr=r;
29: while(tmpr<=hgt){
30: c[i][tmpj][tmpr]++;
31: tmpr+=(-tmpr)&tmpr;
32: }
33: tmpj+=(-tmpj)&tmpj;
34: }
35: i+=(-i)&i;
36: }
37: }
38:
39: int main()
40: {
41: int i,n,m,op,x1,y1,z1,x2,y2,z2;
42: while(~scanf("%d%d",&n,&m)){
43: len=wid=hgt=n;
44: memset(c,0,sizeof(c));
45: for(i=1;i<=m;i++){
46: scanf("%d",&op);
47: if(op==1){
48: scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
49: insert(x1,y1,z1);
50: insert(x1,y1,z2+1);
51: insert(x1,y2+1,z1);
52: insert(x1,y2+1,z2+1);
53:
54: insert(x2+1,y1,z1);
55: insert(x2+1,y1,z2+1);
56: insert(x2+1,y2+1,z1);
57: insert(x2+1,y2+1,z2+1);
58: }
59: else {
60: scanf("%d%d%d",&x1,&y1,&z1);
61: printf("%d/n",getsum(x1,y1,z1)%2);
62: }
63: }
64: }
65: return 0;
66: }
相关文章推荐
- HDU - 3584 Cube (三维树状数组 + 区间改动 + 单点求值)
- HDU 3584 Cube 【 三维树状数组 】
- POJ-2155 Matrix 二维树状数组, HDU-3584 Cube 三维树状数组
- POJ 2155 Matrix ( 二维树状数组 ) || HDU 3584 Cube ( 三维树状数组 )
- hdu 3584 Cube (三维树状数组,更新区间,查询单点)
- HDU - 3584 Cube (三维树状数组 + 区间修改 + 单点求值)
- HDU 3584 Cube --三维树状数组
- HDU 3584 Cube(三位树状数组)
- HDU 3584 Cube(三位树状数组)
- HDU 3584 三维树状数组
- HDU 3584 三维树状数组
- hdu 3584 二进制0,1反转 三维树状数组 及三维树状数组模板
- hdu 3584 Cube(树状数组)
- hdu 3584 三维树状数组 很烦的说
- hdu 3584 三维树状数组 区间 更新 单点求值
- HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
- hdu-Cube(三位树状数组)
- HDU 3584 Cube (三维树状数组)
- hdu 3584 Cube(三维树状数组)
- HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)