传送门:【HDU】4872 ZCC Loves COT
题目分析:方法很巧妙!
三维标记还原二维标记,二维标记还原一维标记,一维标记还原原矩阵。
三维标记:标记二维标记+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 ; }