Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Cube Dividing

Pablo Cubarson is a well-known cubism artist. He is producing a new piece of work using a cuboid which consists of $A \times B \times C$ unit cubes. He plans to make a beautiful shape by removing $N$ units cubes from the cuboid. When he is about to begin the work, he has noticed that by the removal the cuboid may be divided into several parts disconnected to each other. It is against his aesthetics to divide a cuboid. So he wants to know how many parts are created in his plan.

Your task is to calculate the number of connected components in the cuboid after removing the $N$ cubes. Two cubes are connected if they share one face.

Input

The input consists of a single test case. The test case is formatted as follows:

$A$ $B$ $C$ $N$

$X_1$ $Y_1$ $Z_1$

...

$X_N$ $Y_N$ $Z_N$

The first line contains four integers $A$, $B$, $C$ and $N$. $A$, $B$ and $C$ ($1 \leq A,B,C \leq 10^6$) denote the size of the cuboid $-$ the cuboid has an $A$ unit width from left to right and a $B$ unit height from bottom to top, and a $C$ unit depth from front to back. $N$ ($0 \leq N \leq 20,000, N \leq A \times B \times C - 1$) denotes the number of the cubes removed in the Cubarson's plan. Each of the following $N$ lines contains three integers $X_i$ ($0 \leq X_i \leq A-1$), $Y_i$ ($0 \leq Y_i \leq B-1$) and $Z_i$ ($0 \leq Z_i \leq C - 1$). They denote that the cube located at the $X_i$-th position from the left, the $Y_i$-th from the bottom and the $Z_i$-th from the front will be removed in the plan. You may assume the given positions are distinct.

Output

Print the number of the connected components in the cuboid after removing the specified cubes.

Sample Input 1

2 2 2 4
0 0 0
1 1 0
1 0 1
0 1 1

Output for the Sample Input 1

4

Sample Input 2

3 3 3 1
1 1 1

Output for the Sample Input 2

1

Sample Input 3

1 1 3 2
0 0 0
0 0 2

Output for the Sample Input 3

1

Solution in C++14 (judge verdict: Runtime Error)

#include<bits/stdc++.h>
using namespace std;

int A,B,C,N;
const int MAX = 20000*30;
int d[MAX];
void init(){ memset( d, -1, sizeof( d ) ); }
int find(int a){ return d[a]<0?a:(d[a]=find(d[a])); }
bool merge(int a, int b){
  a = find(a); b = find(b);
  if( a == b ) return false;
  if( d[a] > d[b] ) swap( a, b );
  d[a] += d[b]; d[b] = a;
  return true;
}
bool same(int a,int b){
  return find(a) == find(b);
}

struct P3{
  int x,y,z;
  P3(){}
  P3(int x,int y,int z) : x(x),y(y),z(z) {}
  bool operator<(const P3& p) const {
    if( x == p.x )
      if( y == p.y )
        return z < p.z;
      else
        return y < p.y;
    else
      return x< p.x;
  }
};

int dx[]={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1};
int dy[]={ 1, 1, 1, 0, 0, 0, 1,-1,-1, 1, 1, 1, 0, 0, 0,-1,-1,-1, 1, 1, 1, 0, 0, 0,-1,-1,-1};
int dz[]={ 1, 0,-1, 1, 0,-1, 1, 0,-1, 1, 0,-1, 0, 1,-1, 1, 0,-1, 1, 0,-1, 1, 0,-1, 1, 0,-1};
int mx[]={ 1,-1, 0, 0, 0, 0};
int my[]={ 0, 0, 1,-1, 0, 0};
int mz[]={ 0, 0, 0, 0, 1,-1};
map<P3,int> id;
set<P3> umes;
map<int,set<int>> divi;
int cnt;
bitset<100000> used;
bitset<100000> ume;

bool outer(int x,int y, int z ){
  if( x < 0 || x >= A || y < 0 || y >= B || z < 0 || z >= C ) return true;
  return false;
}

bool check( int x,int y,int z, bool f = false ){
  if( outer( x, y, z ) ) return false;
  if( id.count( P3( x, y, z ) ) == 0 ) return false;
  int v = id[ P3(x,y,z) ];
  if( used[ v ] ) return false;
  if( f && !ume[ v ] ) return false;
  if( !f && ume[ v ] ) return false;
  return true;
}

void dfs(int x,int y, int z, bool f = false){
  int v = id[ P3(x,y,z) ];
  if( used[ v ] ) return;
  used[ v ] = true;
  int n = 6;
  if( f ) n = 27;
  for(int i=0;i<n;i++){
    int nx = x + dx[i], ny = y + dy[i], nz = z + dz[i];
    if(!f) nx = x + mx[i], ny = y + my[i], nz = z + mz[i];
    if( check( nx, ny, nz, f ) ) {
      // cout << x << " " << y << " " << z << "  -> " << nx << " " << ny << " " << nz << endl;
      // cout << "merge " << v << " "<< id[P3(nx,ny,nz)] << endl;
      merge( v, id[ P3(nx,ny,nz) ] );
      dfs( nx, ny, nz, f );
    }
  }
}

int main(){
  cin >> A >> B >> C >> N;
  init();
  used = ume = 0;
  for(int i=0;i<N;i++){
    int x,y,z; cin >> x >> y >> z;
    for(int j=0;j<27;j++){
      int nx = x + dx[j], ny = y + dy[j], nz = z + dz[j];
      if( outer( nx, ny, nz ) ) continue;
      if( !id.count( P3( nx,ny,nz) ) ) 
        id[ P3(nx,ny,nz) ] = cnt++;     
    }
    umes.insert( P3(x,y,z) );
    ume[id[P3(x,y,z)]] = true;
  }

  
  for( auto it = id.begin(); it != id.end(); it++ ){
    P3 np = it->first;
    int id = it->second;
    if( ume[id] ) 
      dfs( np.x, np.y, np.z, true );
    else
      dfs( np.x, np.y, np.z );
  }
  
  used = 0;
  for( auto it = umes.begin(); it != umes.end(); it++ ){
    P3 p = *it;
    int v = find( id[p] );
    //cout << p.x << " " << p.y << " " << p.z << " -> " << v << endl;
    for(int i=0;i<27;i++){
      int nx = p.x + dx[i], ny = p.y + dy[i], nz = p.z + dz[i];
      if( id.count( P3(nx,ny,nz) ) == 0 ) continue;
      if( umes.count( P3( nx, ny, nz ) ) ) continue;
      //cout << nx << " " << ny << " "<< nz << " = " << id[P3(nx,ny,nz)] << " <= " << v << endl;
      divi[ v ].insert( find( id[ P3(nx,ny,nz) ] ) );
    }
  }

  int res = 1;
  for( auto it = divi.begin(); it != divi.end(); it++ ){
    res += it->second.size()-1;
  }
  cout << res << endl;
  
}