HDU 3584 Cube 【三維樹狀數組】

【題目地址】

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

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。

(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

 

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”》

 

【代碼】

  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: }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章