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 ; }