【HDU】4872 ZCC Loves COT 三维标记法

传送门:【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 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值