Description
Input
Output
Sample Input
input | output |
---|---|
2 2 1 1 1 1 1 1 1 0 0 0 1 1 0 1 0 3 2 0 0 0 0 0 0 2 0 0 0 0 1 0 1 0 1 0 -2 2 0 0 0 1 1 1 3 |
0 1 4 2 |
描述:Vasya 不明飞行物研究家,他的职责是观察UFO在一个N × N ×N的空间里的存在情况,这个空间被分成1 × 1 × 1的小区域,在这些小区域中会发生下列事件:
一些小区域会出现一些新的UFO;
一些UFO会在一些小区域消失;
Vasya 的上司会询问他某个区域的UFO有多少;
当Vasya开始观察UFO时,在整个区域内没有UFO。
输入:
第一行包含一个整数N(1 ≤ N ≤ 128).。区域的坐标是从0到N-1。
然后又多行描述,每行的第一个数是M。
如果M是1,接着就有四个整数,分别为 x (0 ≤ x < N), y (0 ≤ y < N), z (0 ≤ z < N), K (–20000 ≤ K ≤ 20000),x,y,z表示UFO出现的小区域,K表示UFO出现的数量。
如果M是2,接着就有六个整数 x1, y1, z1, x2, y2, z2 (0 ≤ x1 ≤ x2 < N, 0 ≤ y1 ≤ y2 < N, 0 ≤ z1 ≤ z2 < N),(x1,y1,z1)与(x2,y2,z2)分别表示所求区域的体对角线上的点。
如果M是3,那么Vasya就可以结束任务,回家睡觉了。
输出:
对Vasya上司的每句询问,都输出当前该区域UFO的数量,并且结果占一行。
本题可以利用三维树状数组,其实和一维树状数组,二维树状数组差不多,只是在更新(update)函数和求和(SUM)函数中相对一维、二维树状数组多了两、一个for循环而已,在最后的调用SUM函数是稍复杂些罢了。
代码如下:
//三维树状数组 #include<stdio.h> #include<string.h> #define max 130 int N; //三维树状数组(s[ ][ ][ ])用来储存出现UFO的数量,由于数量值较大,采用long long型 long long s[max][max][max]={0}; int lowbit(int x) { return x&(-x); } //更新函数,对树状数组某一元素(x,y,z)加减某一num值 void update(int x,int y,int z,int num) { int i,j,k; for(i=x;i<=N;i+=lowbit(i)) { for(j=y;j<=N;j+=lowbit(j)) { for(k=z;k<=N;k+=lowbit(k)) s[i][j][k]+=num; } } } //求和函数,对树状数组某区域内的元素求和,注意数值较大,采用long long型 long long SUM(int x,int y,int z) { int i,j,k; long long ans=0; for(i=x;i>0;i-=lowbit(i)) { for(j=y;j>0;j-=lowbit(j)) { for(k=z;k>0;k-=lowbit(k)) ans+=s[i][j][k]; } } return ans; } int main() { long long sum; int x,y,z,x1,x2,y1,y2,z1,z2,M,K; scanf("%d",&N); while(scanf("%d",&M)&&M!=3) { if(M==1) { //输入要更新的元素以及更新的值 scanf("%d%d%d%d",&x,&y,&z,&K); /*对相应元素更新,注意树状数组是 从1开始储存的,输入的元素是从0开始的*/ update(x+1,y+1,z+1,K); } if(M==2) { //输入需要求和的区域 scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2); //求和 sum=SUM(x2+1,y2+1,z2+1)-SUM(x2+1,y2+1,z1)-SUM(x2+1,y1,z2+1)-SUM(x1,y2+1,z2+1)+SUM(x1,y1,z2+1)+SUM(x1,y2+1,z1)+SUM(x2+1,y1,z1)-SUM(x1,y1,z1); printf("%lld\n",sum); } } return 0; }
原文地址:http://blog.csdn.net/yanghuaqings/article/details/38338239