有一个 n ∗ m ∗ l n*m*l n∗m∗l的长方体,每个位置有0/1的权值
对于每个为1的位置,要求包含这个位置且内部全为1的子长方体个数。
n ≤ 60 n\leq 60 n≤60
我们不妨考虑二维该如何数子矩形。
如果我们枚举每个合法的矩形,矩形内部+1,可以在左上角,右下角+1,左下右上-1,做一遍二维前缀和就可以得到答案,三维是类似的。
如果我们能求出每个位置分别作为左上角,右下角,左下角和右上角各出现了多少次,那么就可以直接统计了。
以左上角为例,预处理出每个位置向下距离第一个0还有多少个格子,从右向左扫每个格子,我们发现可以用来做右下角范围成一个递减的东西,可以利用单调栈来维护,我们只需要将贡献拆开,统计单调栈中每个位置的贡献和即可,这一部分可以做到 O ( n 2 ) O(n^2) O(n2)。
拓展到三维,我们可以直接枚举第一维的上下边界,对后两维按照上述方法来做即可。
时间复杂度 O ( n 4 ) O(n^4) O(n4)
#include
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
const int N=62;
using namespace std;
intn,m,l,t,ls[N][N];
LL bz[N][N][N],ct[N][N][N];
bool mp[N][N];
int d[N];
int main()
{
cin>>n>>m>>l;
fo(i,1,n)
{
fo(j,1,m) fo(k,1,l)
{
int x;
scanf("%d",&x);
bz[i][j][k]=1-x;
}
}
fo(i,1,n)
{
memset(mp,0,sizeof(mp));
fo(j,i,n)
{
fo(u,1,m) fo(v,1,l) mp[u][v]|=bz[j][u][v];
//左上,+ -
fod(u,m,1)
{
d[0]=1;
d[1]=l+1;
LL s=0;
fod(v,l,1)
{
ls[u][v]=(mp[u][v])?0:ls[u+1][v]+1;
while(d[0]&&ls[u][v]<ls[u][d[d[0]]])
{
s-=(LL)d[d[0]-1]*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
d[d[0]--]=0;
}
d[++d[0]]=v;
s+=(LL)(d[d[0]-1])*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
ct[i][u][v]+=s-(LL)v*ls[u][d[d[0]]];
ct[j+1][u][v]-=s-(LL)v*ls[u][d[d[0]]];
}
}
//左下 - +
fo(u,1,m)
{
d[0]=1;
d[1]=l+1;
LL s=0;
fod(v,l,1)
{
ls[u][v]=(mp[u][v])?0:ls[u-1][v]+1;
while(d[0]&&ls[u][v]<ls[u][d[d[0]]])
{
s-=(LL)d[d[0]-1]*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
d[d[0]--]=0;
}
d[++d[0]]=v;
s+=(LL)(d[d[0]-1])*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
ct[i][u+1][v]-=s-(LL)v*ls[u][d[d[0]]];
ct[j+1][u+1][v]+=s-(LL)v*ls[u][d[d[0]]];
}
}
//右上 - +
fod(u,m,1)
{
d[0]=1;
d[1]=0;
LL s=0;
fo(v,1,l)
{
ls[u][v]=(mp[u][v])?0:ls[u+1][v]+1;
while(d[0]&&ls[u][v]<ls[u][d[d[0]]])
{
s+=(LL)d[d[0]-1]*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
d[d[0]--]=0;
}
d[++d[0]]=v;
s-=(LL)(d[d[0]-1])*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
ct[i][u][v+1]-=(LL)v*ls[u][d[d[0]]]+s;
ct[j+1][u][v+1]+=(LL)v*ls[u][d[d[0]]]+s;
}
}
//右下 + -
fo(u,1,m)
{
d[0]=1;
d[1]=0;
LL s=0;
fo(v,1,l)
{
ls[u][v]=(mp[u][v])?0:ls[u-1][v]+1;
while(d[0]&&ls[u][v]<ls[u][d[d[0]]])
{
s+=(LL)d[d[0]-1]*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
d[d[0]--]=0;
}
d[++d[0]]=v;
s-=(LL)(d[d[0]-1])*(ls[u][d[d[0]]]-ls[u][d[d[0]-1]]);
ct[i][u+1][v+1]+=(LL)v*ls[u][d[d[0]]]+s;
ct[j+1][u+1][v+1]-=(LL)v*ls[u][d[d[0]]]+s;
}
}
}
}
fo(i,1,n) fo(j,1,m) fo(k,1,l)
{
ct[i][j][k]+=ct[i-1][j][k]+ct[i][j-1][k]+ct[i][j][k-1]-ct[i-1][j-1][k]-ct[i][j-1][k-1]-ct[i-1][j][k-1]+ct[i-1][j-1][k-1];
printf("%d\n",ct[i][j][k]);
}
}