#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string.h>
#include<cmath>
#include<string>
using namespace std;


//
/*************************
题意:
给出一个三维立方体,每个点由0或1构成
问由1构成的体积共多少
且构成的每个体积必须大于t
*************************/

/************************
求解要点:
用并查集方法:
每储存一个1元素,
查看其left、up、below 3个相邻的点
(由于储存时从上往下,从西往东,从北往南,故一定可以利用之前的信息)
若为1,则找到那个点所在集合的父亲(并查集方法)

优先让集合们指向left
若left不存在则指向up,
若up不存在指向below
若都不存在,自身为集合。

同时注意判断重复指向的情况
即up、below、left的父亲可能是同一个集合
要加上判断。
************************/

/***********************
笔记:
1.当让3个集合指向1个时,
设定一个优先级
先指a
a没有则指b,b没有则指c
同时进行是否在同一个集合的判断
若相同集合,则不进行相加操作。
*********************/
#define M 1291
#define N 132
#define K 64
#define INF 0xfffff

struct point
{
int k,i,j;
};

struct father
{
struct point nextp;
bool flag;
int pn;
};

struct father fa[K][M][N];
int a[K][M][N];
int n,m,l;
struct point getf(int k,int i,int j)
{
point p,pa;
p.k=k;p.i=i;p.j=j;

if(a[k][i][j]==0)
{
p.k=-1;
p.i=-1;
p.j=-1;
return p;
}

if(fa[k][i][j].flag==1)
return p;

pa=fa[k][i][j].nextp;
pa=getf(pa.k,pa.i,pa.j);
fa[k][i][j].nextp=pa;

return pa;

}

int main()
{
int t;
scanf("%d%d%d%d",&m,&n,&l,&t);
memset(a,0,sizeof(a));
struct father f,fk,fi,fj,orf;
struct point p,pup,pbelow,pleft,pfa;
int i,j,k;

for(k=0;k<=l+2;k++)
for(i=0;i<=m+2;i++)
for(j=0;j<=n+2;j++)
{
fa[k][i][j].pn=0;
fa[k][i][j].flag=0;
}

for(k=1;k<=l;k++){
for(i=1;i<=m;i++)
for(j=1;j<=n;j++){

scanf("%d",&a[k][i][j]);
//printf("%d %d %d\n",k,i,j);
if(a[k][i][j] == 1){
p.i=i;
p.j=j;
p.k=k;
fa[k][i][j].pn=1;
pbelow=getf(k-1,i,j);
pup=getf(k,i-1,j);
pleft=getf(k,i,j-1);

if(a[k][i][j-1]==1)
pfa=pleft;
else if(a[k][i-1][j]==1)
pfa=pup;
else if(a[k-1][i][j]==1)
pfa=pbelow;
else pfa=p;

fa[pfa.k][pfa.i][pfa.j].flag=1;
fa[pfa.k][pfa.i][pfa.j].nextp=pfa;



//若上一行非0,则加上去,但前提是不与pfa相同
//与pfa相同则代表: 可能为left,可能为up
if(pup.k!=-1){
if(pup.k!=pfa.k || pup.i!=pfa.i || pup.j!=pfa.j){
fa[pup.k][pup.i][pup.j].nextp = pfa;
fa[pfa.k][pfa.i][pfa.j].pn += fa[pup.k][pup.i][pup.j].pn;
fa[pup.k][pup.i][pup.j].flag=0;
}
}

//若上一层非0,则加上去,但前提是不与pfa相同,且不与below相同。
//即如果要指向left,而below和up父亲相同,则只需要加一次即可
//与pfa相同则代表: 可能为left,可能为up,可能为below
if(pbelow.k!=-1){
//注意如果below的父亲和up的父亲相同,说明在同一集合
//则below不可加。
if(pbelow.k!=pfa.k || pbelow.i!=pfa.i || pbelow.j!=pfa.j){
if(pbelow.k!=pup.k || pbelow.i!=pup.i || pbelow.j!=pup.j)
{
fa[pbelow.k][pbelow.i][pbelow.j].nextp = pfa;
fa[pfa.k][pfa.i][pfa.j].pn += fa[pbelow.k][pbelow.i][pbelow.j].pn;
fa[pbelow.k][pbelow.i][pbelow.j].flag=0;
}
}
}


if(k!=pfa.k || i!=pfa.i || j!=pfa.j)
{
fa[k][i][j].nextp = pfa;
fa[pfa.k][pfa.i][pfa.j].pn += 1;
fa[k][i][j].flag=0;
}

}
}
}

int ans=0;

for(k=1;k<=l;k++)
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(fa[k][i][j].flag==1 && fa[k][i][j].pn >= t)
{
ans+=fa[k][i][j].pn;
}
}

cout<<ans<<endl;
return 0;
}