http://acm.hdu.edu.cn/showproblem.php?pid=3642
题意:
给你N个立方体,求空间中被不同的立方体覆盖至少3次的体积。
思路:
这个题目是一个三维空间的体积交的题,和HDU1255的面积交是差不多的,本题可以先将Z轴离散化,然后对于每个Z轴上的区间,只要求出此时的合法面积然后再乘以Z轴上的高度就可以了。每次求合法面积的时候只要用二维的矩形面积交,然后求出至少覆盖三次的面积就可以了。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define LL(a) ( (a)<<1 )
#define RR(a) ( (a)<<1|1 )
#define STOP system("pause")
#define MAX(a , b) ( (a)>(b)?(a):(b) )
#define MIN(a , b) ( (a)>(b)?(b):(a) )
using namespace std;
const int MAXN = 5050 ;
struct point{
int x, y, z ;
point(){}
point(int a, int b, int c)
: x(a) , y(b) , z(c){}
};
struct Node{
point p1,p2;
void init(int a, int b ,int c ,int a1, int b1, int c1){
p1 = point(a ,b , c ) ;
p2 = point(a1 , b1 , c1 );
}
}p[MAXN] ;
struct Seg{
int l ,r , h , s ;
Seg(){}
Seg(int a, int b , int c , int d )
:l(a), r(b) , h(c) , s(d) {}
bool operator< (const Seg& cmp )const {
return h < cmp.h ;
}
}pp[MAXN] ;
int N ;
int X[MAXN] ;
int col[MAXN<<2] ;
int sum1[MAXN<<2] , sum2[MAXN<<2] , sum3[MAXN<<2] ;
int Z[MAXN] ;
int find(int val , int l , int r ){
while( l < r ){
int mid = (l + r) >> 1 ;
if( X[mid] < val )
l = mid + 1 ;
else
r = mid ;
}
return l ;
}
void pushup(int l ,int r , int idx){
int ls = LL(idx) , rs = RR(idx) ;
if( col[idx] >= 3 ){
sum1[idx] = sum2[idx] = 0 ;
sum3[idx] = X[r+1] - X[l] ;
}
else if( col[idx] == 2 ){
sum1[idx] = 0 ;
if(l == r) sum3[idx] = 0 ;
else sum3[idx] = sum3[ls] + sum3[rs] + sum2[ls] + sum2[rs] + sum1[ls] + sum1[rs] ;
sum2[idx] = X[r+1] - X[l] - sum3[idx] ;
}
else if( col[idx] == 1){
if(l == r){
sum2[idx] = sum3[idx] = 0 ;
}
else{
sum3[idx] = sum3[ls] + sum3[rs] + sum2[ls] + sum2[rs] ;
sum2[idx] = sum1[ls] + sum1[rs] ;
}
sum1[idx] = X[r+1] - X[l] - sum2[idx] - sum3[idx] ;
}
else{
if(l == r ) sum3[idx] = sum2[idx] = sum1[idx] = 0 ;
else{
sum1[idx] = sum1[ls] + sum1[rs] ;
sum2[idx] = sum2[ls] + sum2[rs] ;
sum3[idx] = sum3[ls] + sum3[rs] ;
}
}
}
void update(int l ,int r, int idx, int a, int b, int v ){
if(l==a && r==b ){
col[idx] += v ;
pushup(l , r , idx );
return ;
}
int mid = (l + r) >> 1;
if( b<=mid ) update(l, mid , LL(idx) ,a ,b , v );
else if( mid<a ) update(mid+1, r, RR(idx) , a, b , v );
else{
update(l ,mid, LL(idx) , a , mid , v );
update(mid+1 ,r , RR(idx) ,mid+1, b , v );
}
pushup(l, r ,idx);
}
void build(int l ,int r, int idx){
sum1[idx] = sum2[idx] = sum3[idx] = col[idx] = 0 ;
if( l == r ) return ;
int mid = (l + r) >> 1;
build(l, mid , LL(idx));
build(mid+1, r ,RR(idx));
}
int nn ;
void solve(){
int m , n ,tot;
__int64 res = 0 ;
for(int i=0;i<nn;i++) {
int c1 = Z[i] , c2 = Z[i+1] ;
m = 0 ; tot = 0 ;
for(int i=0;i<N;i++){
int x1 = p[i].p1.x ;
int x2 = p[i].p2.x ;
int y1 = p[i].p1.y ;
int y2 = p[i].p2.y ;
int z1 = p[i].p1.z ;
int z2 = p[i].p2.z ;
if( z1<=c1 && z2>=c2 ){
X[m] = x1 ;
pp[m++] = Seg(x1 , x2 , y1 , 1 );
X[m] = x2 ;
pp[m++] = Seg(x1 , x2 , y2 , -1 );
}
}
sort(X , X + m);
sort(pp , pp + m );
n = 1 ;
for(int i=1;i<m;i++)
if( X[i] != X[i-1] )
X[n++] = X[i] ;
n-- ;
build(0 , n , 1 );
__int64 ans = 0 ;
for(int i=0;i<m-1;i++){
int s = find(pp[i].l , 0 , n ) ;
int e = find(pp[i].r , 0 , n ) - 1 ;
if(s <= e){
update(0, n , 1 , s ,e , pp[i].s );
}
ans += (__int64)(sum3[1])*(__int64)( pp[i+1].h - pp[i].h ) ;
}
res += ans*(__int64)(c2-c1);
}
printf("%I64d\n",res);
}
int main(){
int t , tt ;
int a , b ,c , a1, b1, c1 ;
scanf("%d",&tt);
for(t = 0 ; t<tt ; t ++){
scanf("%d",&N);
int m = 0 ;
for(int i=0;i<N;i++){
scanf("%d%d%d%d%d%d",&a,&b,&c,&a1,&b1,&c1);
p[i].init(a,b,c,a1,b1,c1);
Z[m++] = c ; Z[m++] = c1 ; //离散化Z轴
}
sort(Z, Z+m );
nn = 1 ;
for(int i=1;i<m;i++) //压缩
if( Z[i] != Z[i-1] ) Z[nn++] = Z[i] ;
nn-- ;
printf("Case %d: ",t+1);
solve() ;
}
return 0 ;
}