Given a 3D matrix mat[][][] of size NXNXN with all its elements initialized to 0, the task is to answer Q queries. The queries are given in the form of 2D matrix queries[][], where each queries[i] can be one of the following types:
Type 1 [1, x, y, z, ele]: Update the value of cell(x, y, z) to Val.
Type 2 [2, x, y, z, X, Y, Z]: Print the sum of the submatrix (x, y, z) to (X, Y, Z)
Print the answer to all the queries of type 2. The matrix and queries follow 0-based indexing.
Examples:
Input: N = 2, Q = 2, queries[][] = {{1, 0, 0, 0, 1}, {2, 0, 0, 0, 1, 1, 1}} Output: 1 Explanation: In the type-2 query, the sum of subarray from (0, 0, 0) to (1, 1, 1) is 1.
Input: N = 10, Q = 6, queries[][] = {{1, 0, 0, 6, 6}, {1, 9, 9, 9, 10}, {1, 8, 5, 9, 5}, {2, 3, 4, 5, 9, 10, 9}, {1, 6, 6, 1, 23}, {2, 0, 0, 0, 8, 9, 10}} Output: 6 10 Explanation: In the first type-2 query, the sum of subarray from (3, 4, 5) to (9, 10, 9) is 6. In the subsequent type-2 query, the sum of subarray from (0,0,0) to (8,9,10) is 10.
Approach: The problem can be solved using the following approach:
The approach is to implement a 3D binary indexed tree (also known as a Fenwick Tree) to store the Partial Sums of ranges and efficiently update and query ranges in a 3D space. The program takes a series of queries, where each query is either an update or a range query.
Steps to solve the problem:
- Use a 3D array BIT[][][] to store Partial Sums of mat[][][].
- Define a function updateQuery(x, y, z, val) to update the BIT with a given value at position (x, y, z) by updating the values at positions where Partial sum of submatrix[0][0][0] to [x][y][z] is stored.
- It uses three nested loops to iterate over all positions in the BIT that need to be updated based on the given position (x, y, z).
- Define a function sumQuery(x, y, z) to calculate the cumulative sum of the values in the BIT up to position (x, y, z), that is the sum of submatrix[0, 0, 0] to [x, y, z].
- It uses three nested loops similar to updateQuery() but only sums up the values instead of updating them.
- Define a function matrixSumQuery(x, y, z, X, Y, Z) to calculate the sum of values in the given 3D submatrix defined by two opposite corners (x, y, z) and (X, Y, Z).
- It uses the cumulative sum calculated by reading at the eight corners of the cube defined by the given range and get its sum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
ll BIT[102][102][102];
int N;
void updateQuery( int x, int y, int z, ll val)
{
int i, j, k;
for (i = x; i <= N; i += i & -i) {
for (j = y; j <= N; j += j & -j) {
for (k = z; k <= N; k += k & -k) {
BIT[i][j][k] += val;
}
}
}
}
ll sumQuery( int x, int y, int z)
{
ll sum = 0;
int i, j, k;
for (i = x; i > 0; i -= i & -i) {
for (j = y; j > 0; j -= j & -j) {
for (k = z; k > 0; k -= k & -k) {
sum += BIT[i][j][k];
}
}
}
return sum;
}
ll matrixSumQuery( int x, int y, int z, int X, int Y, int Z)
{
return sumQuery(X, Y, Z) - sumQuery(x, Y, Z)
- sumQuery(X, y, Z) - sumQuery(X, Y, z)
+ sumQuery(x, y, Z) + sumQuery(x, Y, z)
+ sumQuery(X, y, z) - sumQuery(x, y, z);
}
int main()
{
int Q, type, x, y, z, val, X, Y, Z;
N = 10;
Q = 6;
ll queries[Q][7]
= { { 1, 0, 0, 6, 6 }, { 1, 9, 9, 9, 10 },
{ 1, 8, 5, 9, 5 }, { 2, 3, 4, 5, 9, 10, 9 },
{ 1, 6, 6, 1, 23 }, { 2, 0, 0, 0, 8, 9, 10 } };
for ( int i = 0; i < Q; i++) {
type = queries[i][0];
if (type == 1) {
x = queries[i][1];
y = queries[i][2];
z = queries[i][3];
val = queries[i][4];
updateQuery(x + 1, y + 1, z + 1, val);
}
else {
x = queries[i][1];
y = queries[i][2];
z = queries[i][3];
X = queries[i][4];
Y = queries[i][5];
Z = queries[i][6];
cout << matrixSumQuery(x, y, z, X + 1, Y + 1,
Z + 1)
<< "\n" ;
}
}
return 0;
}
|
Java
import java.util.Scanner;
public class BIT3D {
static long [][][] BIT;
static int N;
static void updateQuery( int x, int y, int z, long val) {
for ( int i = x; i <= N + 1 ; i += i & -i) {
for ( int j = y; j <= N + 1 ; j += j & -j) {
for ( int k = z; k <= N + 1 ; k += k & -k) {
BIT[i][j][k] += val;
}
}
}
}
static long sumQuery( int x, int y, int z) {
long sum = 0 ;
for ( int i = x; i > 0 ; i -= i & -i) {
for ( int j = y; j > 0 ; j -= j & -j) {
for ( int k = z; k > 0 ; k -= k & -k) {
sum += BIT[i][j][k];
}
}
}
return sum;
}
static long matrixSumQuery( int x, int y, int z, int X, int Y, int Z) {
return sumQuery(X, Y, Z) - sumQuery(x - 1 , Y, Z) - sumQuery(X, y - 1 , Z) - sumQuery(X, Y, z - 1 )
+ sumQuery(x - 1 , y - 1 , z - 1 ) - sumQuery(x - 1 , Y, z - 1 ) - sumQuery(X, y - 1 , z - 1 )
+ sumQuery(x - 1 , y - 1 , Z) + sumQuery(x - 1 , Y, z) + sumQuery(X, y - 1 , z);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = 10 ;
int Q = 6 ;
BIT = new long [N + 2 ][N + 2 ][N + 2 ];
long [][] queries = { { 1 , 0 , 0 , 6 , 6 }, { 1 , 9 , 9 , 9 , 10 }, { 1 , 8 , 5 , 9 , 5 }, { 2 , 3 , 4 , 5 , 9 , 10 , 9 },
{ 1 , 6 , 6 , 1 , 23 }, { 2 , 0 , 0 , 0 , 8 , 9 , 10 } };
for ( int i = 0 ; i < Q; i++) {
int type = ( int ) queries[i][ 0 ];
if (type == 1 ) {
int x = ( int ) queries[i][ 1 ];
int y = ( int ) queries[i][ 2 ];
int z = ( int ) queries[i][ 3 ];
long val = queries[i][ 4 ];
updateQuery(x + 1 , y + 1 , z + 1 , val);
} else {
int x = ( int ) queries[i][ 1 ];
int y = ( int ) queries[i][ 2 ];
int z = ( int ) queries[i][ 3 ];
int X = ( int ) queries[i][ 4 ];
int Y = ( int ) queries[i][ 5 ];
int Z = ( int ) queries[i][ 6 ];
System.out.println(matrixSumQuery(x, y, z, X + 1 , Y + 1 , Z + 1 ));
}
}
sc.close();
}
}
|
Python3
BIT = [[[ 0 for _ in range ( 102 )] for _ in range ( 102 )] for _ in range ( 102 )]
N = 0
def updateQuery(x, y, z, val):
global BIT
i, j, k = x, y, z
while i < = N:
j = y
while j < = N:
k = z
while k < = N:
BIT[i][j][k] + = val
k + = k & - k
j + = j & - j
i + = i & - i
def sumQuery(x, y, z):
global BIT
sum = 0
i, j, k = x, y, z
while i > 0 :
j = y
while j > 0 :
k = z
while k > 0 :
sum + = BIT[i][j][k]
k - = k & - k
j - = j & - j
i - = i & - i
return sum
def matrixSumQuery(x, y, z, X, Y, Z):
return sumQuery(X, Y, Z) - sumQuery(x, Y, Z) - sumQuery(X, y, Z) - sumQuery(X, Y, z) + sumQuery(x, y, Z) + sumQuery(x, Y, z) + sumQuery(X, y, z) - sumQuery(x, y, z)
N = 10
Q = 6
queries = [[ 1 , 0 , 0 , 6 , 6 ], [ 1 , 9 , 9 , 9 , 10 ], [ 1 , 8 , 5 , 9 , 5 ], [ 2 , 3 , 4 , 5 , 9 , 10 , 9 ], [ 1 , 6 , 6 , 1 , 23 ], [ 2 , 0 , 0 , 0 , 8 , 9 , 10 ]]
for i in range (Q):
type = queries[i][ 0 ]
if type = = 1 :
x = queries[i][ 1 ]
y = queries[i][ 2 ]
z = queries[i][ 3 ]
val = queries[i][ 4 ]
updateQuery(x + 1 , y + 1 , z + 1 , val)
else :
x = queries[i][ 1 ]
y = queries[i][ 2 ]
z = queries[i][ 3 ]
X = queries[i][ 4 ]
Y = queries[i][ 5 ]
Z = queries[i][ 6 ]
print (matrixSumQuery(x, y, z, X + 1 , Y + 1 , Z + 1 ))
|
C#
using System;
class MainClass
{
const int N = 10;
const int Q = 6;
static int [][][] BIT = new int [102][][];
static void Main()
{
for ( int i = 0; i < BIT.Length; i++)
{
BIT[i] = new int [102][];
for ( int j = 0; j < BIT[i].Length; j++)
{
BIT[i][j] = new int [102];
}
}
int [][] queries = new int [][] {
new int [] {1, 0, 0, 6, 6},
new int [] {1, 9, 9, 9, 10},
new int [] {1, 8, 5, 9, 5},
new int [] {2, 3, 4, 5, 9, 10, 9},
new int [] {1, 6, 6, 1, 23},
new int [] {2, 0, 0, 0, 8, 9, 10},
};
for ( int i = 0; i < Q; i++)
{
int type = queries[i][0];
int x, y, z, val, X, Y, Z;
if (type == 1)
{
x = queries[i][1];
y = queries[i][2];
z = queries[i][3];
val = queries[i][4];
UpdateQuery(x + 1, y + 1, z + 1, val);
}
else
{
x = queries[i][1];
y = queries[i][2];
z = queries[i][3];
X = queries[i][4];
Y = queries[i][5];
Z = queries[i][6];
Console.WriteLine(MatrixSumQuery(x, y, z, X + 1, Y + 1, Z + 1));
}
}
}
static void UpdateQuery( int x, int y, int z, int val)
{
for ( int i = x; i <= N; i += i & -i)
{
for ( int j = y; j <= N; j += j & -j)
{
for ( int k = z; k <= N; k += k & -k)
{
BIT[i][j][k] += val;
}
}
}
}
static int SumQuery( int x, int y, int z)
{
int sum = 0;
for ( int i = x; i > 0; i -= i & -i)
{
for ( int j = y; j > 0; j -= j & -j)
{
for ( int k = z; k > 0; k -= k & -k)
{
sum += BIT[i][j][k];
}
}
}
return sum;
}
static int MatrixSumQuery( int x, int y, int z, int X, int Y, int Z)
{
return (
SumQuery(X, Y, Z) - SumQuery(x, Y, Z) - SumQuery(X, y, Z) - SumQuery(X, Y, z) +
SumQuery(x, y, Z) + SumQuery(x, Y, z) + SumQuery(X, y, z) - SumQuery(x, y, z)
);
}
}
|
Javascript
const N = 10;
const Q = 6;
const BIT = new Array(102).fill( null ).map(() =>
new Array(102).fill( null ).map(() => new Array(102).fill(0))
);
function updateQuery(x, y, z, val) {
for (let i = x; i <= N; i += i & -i) {
for (let j = y; j <= N; j += j & -j) {
for (let k = z; k <= N; k += k & -k) {
BIT[i][j][k] += val;
}
}
}
}
function sumQuery(x, y, z) {
let sum = 0;
for (let i = x; i > 0; i -= i & -i) {
for (let j = y; j > 0; j -= j & -j) {
for (let k = z; k > 0; k -= k & -k) {
sum += BIT[i][j][k];
}
}
}
return sum;
}
function matrixSumQuery(x, y, z, X, Y, Z) {
return (
sumQuery(X, Y, Z) - sumQuery(x, Y, Z) - sumQuery(X, y, Z) - sumQuery(X, Y, z) +
sumQuery(x, y, Z) + sumQuery(x, Y, z) + sumQuery(X, y, z) - sumQuery(x, y, z)
);
}
const queries = [
[1, 0, 0, 6, 6],
[1, 9, 9, 9, 10],
[1, 8, 5, 9, 5],
[2, 3, 4, 5, 9, 10, 9],
[1, 6, 6, 1, 23],
[2, 0, 0, 0, 8, 9, 10],
];
for (let i = 0; i < Q; i++) {
const type = queries[i][0];
let x, y, z, val, X, Y, Z;
if (type === 1) {
x = queries[i][1];
y = queries[i][2];
z = queries[i][3];
val = queries[i][4];
updateQuery(x + 1, y + 1, z + 1, val);
}
else {
x = queries[i][1];
y = queries[i][2];
z = queries[i][3];
X = queries[i][4];
Y = queries[i][5];
Z = queries[i][6];
console.log(matrixSumQuery(x, y, z, X + 1, Y + 1, Z + 1));
}
}
|
Time Complexity: O(Q * log(N) * log(N) * log(N))
- Both updateQuery(x, y, z, val) function and matrixSumQuery(x, y, z, X, Y, Z) function takes O(log(N)*log(N)*log(N)) time.
- So, the overall time complexity for Q queries is O(Q*log(N)*log(N)*log(N)).
Auxiliary Space: O(N * N * N)
|