题目分析:方法很巧妙!
三维标记还原二维标记,二维标记还原一维标记,一维标记还原原矩阵。
三维标记:标记二维标记+1的开头和结尾,标记二维标记-1的开头和结尾。
扫描一遍三维标记得到二维标记。
二维标记:标记一维标记+1的开头和结尾,标记一维标记-1的开头和结尾。
扫描一遍二维标记得到一维标记。
扫描一遍一维标记得到原矩阵。
然后是求前缀和。
不好描述。。。具体思想和标记类似。。。。真想看明白的话还是看代码比较好。。。。
然后渣渣我老是细节方面出一点问题,查了蛮久的错。。。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define REV( i , n ) for ( int i = n - 1 ; i >= 0 ; -- i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define FOV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define REPF( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define REPV( i , a , b ) for ( int i = a - 1 ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define MAXN 105
#define SIZE MAXN][MAXN][MAXN
//如果不好理解的话就用注释掉的循环来理解吧,就是效率不高而已
//#define FFF FOR ( i , 1 , N ) FOR ( j , 1 , N ) FOR ( k , 1 , N )
//#define VVV FOV ( i , N , 1 ) FOV ( j , N , 1 ) FOV ( k , N , 1 )
#define FFF FOR ( i , 1 , N ) FOR ( j , 1 , i ) FOR ( k , 1 , j )
#define VVV FOV ( i , N , 1 ) FOV ( j , i , 1 ) FOV ( k , j , 1 )
typedef long long LL ;
//各字母含义:
//d3三维 d2二维 d1一维
//a:add d:del s:start e:end
int d3as[SIZE] , d3ae[SIZE] , d3ds[SIZE] , d3de[SIZE] ;
LL d2a[SIZE] , d2d[SIZE] ;
LL d1[SIZE] ;
LL suffix1d[SIZE] , suffix2d[SIZE] ;
LL s1[SIZE] , s2[SIZE] , s31[SIZE] , s32[SIZE] ;
//s1 与四面体同形状
//s2 为竖立的三棱柱
//s31为立方体
//s32为平躺的三棱柱
int N , M , Q ;
void DEBUG ( LL a[][MAXN][MAXN] ) {
for ( int z = 1 ; z <= N ; ++ z ) {
for ( int y = N ; y >= 1 ; -- y ) {
for ( int x = 1 ; x <= N ; ++ x )
printf ( "%lld " , a[x][y][z] ) ;
printf ( "\n" ) ;
}
printf ( "\n" ) ;
}
}
void read ( int &x ) {
x = 0 ;
char c = ' ' ;
while ( c < '0' || c > '9' )
c = getchar () ;
while ( c >= '0' && c <= '9' ) {
x = x * 10 + c - '0' ;
c = getchar () ;
}
}
void solve () {
int x , y , z , a ;
CLR ( d3as , 0 ) ;
CLR ( d3ae , 0 ) ;
CLR ( d3ds , 0 ) ;
CLR ( d3de , 0 ) ;
CLR ( d2a , 0 ) ;
CLR ( d2d , 0 ) ;
CLR ( d1 , 0 ) ;
CLR ( suffix1d , 0 ) ;
CLR ( suffix2d , 0 ) ;
CLR ( s1 , 0 ) ;
CLR ( s2 , 0 ) ;
CLR ( s31 , 0 ) ;
CLR ( s32 , 0 ) ;
REP ( i , M ) {//标记三维标记
read ( x ) , read ( y ) , read ( z ) , read ( a ) ;
d3as[x ][y ][z ] ++ ;
d3as[x + a][y + a][z + a] -- ;
d3ae[x + a][y + a][z ] -- ;
d3ae[x + a][y + a][z + a] ++ ;
d3ds[x + a][y ][z ] -- ;
d3ds[x + a][y + a][z + a] ++ ;
d3de[x + a][y + a][z ] ++ ;
d3de[x + a][y + a][z + a] -- ;
}
FFF {//三维还原二维
d2a[i][j][k] += d3as[i][j][k] ;
d2a[i][j][k] += d3ae[i][j][k] ;
d2d[i][j][k] += d3ds[i][j][k] ;
d2d[i][j][k] += d3de[i][j][k] ;
d3as[i + 1][j + 1][k + 1] += d3as[i][j][k] ;
d3ae[i ][j ][k + 1] += d3ae[i][j][k] ;
d3ds[i ][j + 1][k + 1] += d3ds[i][j][k] ;
d3de[i ][j ][k + 1] += d3de[i][j][k] ;
}
FFF {//二维还原一维
d1[i][j][k] += d2a[i][j][k] ;
d1[i][j][k] += d2d[i][j][k] ;
d2a[i + 1][j + 1][k ] += d2a[i][j][k] ;
d2d[i ][j + 1][k ] += d2d[i][j][k] ;
}
FFF {//一维还原原矩阵
suffix1d[i][j][k] += d1[i][j][k] ;//suffix1d这里顺便充当原矩阵功能(节省空间开销)
d1[i + 1][j][k] += d1[i][j][k] ;
}
//接下来是一串的求各种形状的前缀和
VVV suffix1d[i][j][k] += suffix1d[i + 1][j ][k ] ;
VVV suffix2d[i][j][k] += suffix1d[i ][j ][k ] + suffix2d[i + 1][j + 1][k ] ;
VVV s1[i][j][k] += suffix2d[i ][j ][k ] + s1[i + 1][j + 1][k + 1] ;
VVV s2[i][j][k] += suffix2d[i ][j ][k ] + s2[i ][j ][k + 1] ;
VVV s31[i][j][k] += suffix1d[i ][j ][k ] + s31[i ][j + 1][k ] ;
VVV s32[i][j][k] += s31[i ][j ][k ] + s32[i ][j + 1][k + 1] ;
VVV s31[i][j][k] += s31[i ][j ][k + 1] ;
//DEBUG ( s32 ) ;
REP ( i , Q ) {
read ( x ) , read ( y ) , read ( z ) , read ( a ) ;
LL ans = 0 ;
ans += s1[x ][y ][z ] - s1[x + a][y + a][z + a] ;//1.
ans -= s2[x + a][y + a][z ] - s2[x + a][y + a][z + a] ;//2.
ans += s31[x + a][y + a][z ] - s31[x + a][y + a][z + a] ;//3.
ans -= s32[x + a][y ][z ] - s32[x + a][y + a][z + a] ;//4.
printf ( "%I64d\n" , ans ) ;
}
}
int main () {
while ( ~scanf ( "%d%d%d" , &N , &M , &Q ) )
solve () ;
return 0 ;
}